[gjs/wip/ptomato/develop: 11/11] coverage: Stop using cache
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/ptomato/develop: 11/11] coverage: Stop using cache
- Date: Sat, 30 Sep 2017 06:44:43 +0000 (UTC)
commit 3214ab52e666d91ec81ba214e7d853d01e587dfe
Author: Philip Chimento <philip chimento gmail com>
Date: Fri Sep 29 18:15:44 2017 -0700
coverage: Stop using cache
Now that we don't have to do quite so much analysis of JS scripts' ASTs,
it's quite feasible to do the whole coverage thing without caching. A
test run with coverage doesn't take very much longer than a test run
without.
https://bugzilla.gnome.org/show_bug.cgi?id=788166
gjs-srcs.mk | 1 -
gjs/coverage-internal.h | 68 ---
gjs/coverage.cpp | 403 +-----------------
installed-tests/js/testCoverage.js | 70 ---
modules/_bootstrap/coverage.js | 74 +---
test/gjs-test-coverage.cpp | 868 +-----------------------------------
6 files changed, 13 insertions(+), 1471 deletions(-)
---
diff --git a/gjs-srcs.mk b/gjs-srcs.mk
index 36f29a7..1c61c60 100644
--- a/gjs-srcs.mk
+++ b/gjs-srcs.mk
@@ -52,7 +52,6 @@ gjs_srcs = \
gjs/byteArray.h \
gjs/context.cpp \
gjs/context-private.h \
- gjs/coverage-internal.h \
gjs/coverage.cpp \
gjs/engine.cpp \
gjs/engine.h \
diff --git a/gjs/coverage.cpp b/gjs/coverage.cpp
index d7b6d49..c9659e7 100644
--- a/gjs/coverage.cpp
+++ b/gjs/coverage.cpp
@@ -23,13 +23,11 @@
* Authored By: Sam Spilsbury <sam endlessm com>
*/
-#include <sys/stat.h>
#include <gio/gio.h>
#include <gjs/context.h>
#include "coverage.h"
-#include "coverage-internal.h"
#include "global.h"
#include "importer.h"
#include "jsapi-util-args.h"
@@ -45,9 +43,6 @@ typedef struct {
JS::Heap<JSObject *> coverage_statistics;
GFile *output_dir;
- GFile *cache;
- /* tells whether priv->cache == NULL means no cache, or not specified */
- bool cache_specified;
} GjsCoveragePrivate;
G_DEFINE_TYPE_WITH_PRIVATE(GjsCoverage,
@@ -58,7 +53,6 @@ enum {
PROP_0,
PROP_PREFIXES,
PROP_CONTEXT,
- PROP_CACHE,
PROP_OUTPUT_DIRECTORY,
PROP_N
};
@@ -891,164 +885,6 @@ get_covered_files(GjsCoverage *coverage)
return NULL;
}
-bool
-gjs_get_file_mtime(GFile *file,
- GTimeVal *mtime)
-{
- GError *error = NULL;
- GFileInfo *info = g_file_query_info(file,
- "time::modified,time::modified-usec",
- G_FILE_QUERY_INFO_NONE,
- NULL,
- &error);
-
- if (!info) {
- char *path = get_file_identifier(file);
- g_warning("Failed to get modification time of %s, "
- "falling back to checksum method for caching. Reason was: %s",
- path, error->message);
- g_clear_object(&info);
- return false;
- }
-
- g_file_info_get_modification_time(info, mtime);
- g_clear_object(&info);
-
- /* For some URI types, eg, resources, the operation getting
- * the mtime might succeed, but by default zero is returned.
- *
- * Check if that is the case for both tv_sec and tv_usec and if
- * so return false. */
- return !(mtime->tv_sec == 0 && mtime->tv_usec == 0);
-}
-
-static GBytes *
-read_all_bytes_from_file(GFile *file)
-{
- /* We have to use g_file_query_exists here since
- * g_file_test(path, G_FILE_TEST_EXISTS) is implemented in terms
- * of access(), which doesn't work with resource paths. */
- if (!g_file_query_exists(file, NULL))
- return NULL;
-
- gsize len = 0;
- gchar *data = NULL;
-
- GError *error = NULL;
-
- if (!g_file_load_contents(file,
- NULL,
- &data,
- &len,
- NULL,
- &error)) {
- char *path = get_file_identifier(file);
- g_critical("Unable to read bytes from: %s, reason was: %s\n",
- path, error->message);
- g_clear_error(&error);
- g_free(path);
- return NULL;
- }
-
- return g_bytes_new_take(data, len);
-}
-
-gchar *
-gjs_get_file_checksum(GFile *file)
-{
- GBytes *data = read_all_bytes_from_file(file);
-
- if (!data)
- return NULL;
-
- gchar *checksum = g_compute_checksum_for_bytes(G_CHECKSUM_SHA512, data);
-
- g_bytes_unref(data);
- return checksum;
-}
-
-GBytes *
-gjs_serialize_statistics(GjsCoverage *coverage)
-{
- GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage);
- JSContext *js_context = (JSContext *) gjs_context_get_native_context(priv->context);
-
- JSAutoRequest ar(js_context);
- JSAutoCompartment ac(js_context, priv->coverage_statistics);
- JS::RootedObject rooted_priv(js_context, priv->coverage_statistics);
- JS::RootedValue string_value_return(js_context);
-
- if (!JS_CallFunctionName(js_context, rooted_priv, "stringify",
- JS::HandleValueArray::empty(),
- &string_value_return)) {
- gjs_log_exception(js_context);
- return NULL;
- }
-
- if (!string_value_return.isString())
- return NULL;
-
- /* Free'd by g_bytes_new_take */
- GjsAutoJSChar statistics_as_json_string(js_context);
-
- if (!gjs_string_to_utf8(js_context,
- string_value_return.get(),
- &statistics_as_json_string)) {
- gjs_log_exception(js_context);
- return NULL;
- }
-
- int json_string_len = strlen(statistics_as_json_string);
- auto json_bytes =
- reinterpret_cast<uint8_t*>(statistics_as_json_string.copy());
-
- return g_bytes_new_take(json_bytes,
- json_string_len);
-}
-
-static JSString *
-gjs_deserialize_cache_to_object_for_compartment(JSContext *context,
- JS::HandleObject global_object,
- GBytes *cache_data)
-{
- JSAutoRequest ar(context);
- JSAutoCompartment ac(context,
- JS_GetGlobalForObject(context,
- global_object));
-
- gsize len = 0;
- auto string = static_cast<const char *>(g_bytes_get_data(cache_data, &len));
-
- return JS_NewStringCopyN(context, string, len);
-}
-
-JSString *
-gjs_deserialize_cache_to_object(GjsCoverage *coverage,
- GBytes *cache_data)
-{
- /* Deserialize into an object with the following structure:
- *
- * object = {
- * 'filename': {
- * contents: (file contents),
- * nLines: (number of lines in file),
- * branches: Array for n_branches of {
- * point: branch_point,
- * exits: Number[nLines + 1]
- * }
- * }
- * }
- */
-
- GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage);
- JSContext *context = (JSContext *) gjs_context_get_native_context(priv->context);
- JSAutoRequest ar(context);
- JSAutoCompartment ac(context, priv->coverage_statistics);
- JS::RootedObject global_object(context,
- JS_GetGlobalForObject(context, priv->coverage_statistics));
- return gjs_deserialize_cache_to_object_for_compartment(context, global_object, cache_data);
-}
-
static GArray *
gjs_fetch_statistics_from_js(GjsCoverage *coverage,
gchar **coverage_files)
@@ -1082,64 +918,6 @@ gjs_fetch_statistics_from_js(GjsCoverage *coverage,
return file_statistics_array;
}
-bool
-gjs_write_cache_file(GFile *file,
- GBytes *cache)
-{
- gsize cache_len = 0;
- char *cache_data = (char *) g_bytes_get_data(cache, &cache_len);
- GError *error = NULL;
-
- if (!g_file_replace_contents(file,
- cache_data,
- cache_len,
- NULL,
- false,
- G_FILE_CREATE_NONE,
- NULL,
- NULL,
- &error)) {
- char *path = get_file_identifier(file);
- g_warning("Failed to write all bytes to %s, reason was: %s\n",
- path, error->message);
- g_warning("Will remove this file to prevent inconsistent cache "
- "reads next time.");
- g_clear_error(&error);
- if (!g_file_delete(file, NULL, &error)) {
- g_assert(error != NULL);
- g_critical("Deleting %s failed because %s! You will need to "
- "delete it manually before running the coverage "
- "mode again.", path, error->message);
- g_clear_error(&error);
- }
- g_free(path);
-
- return false;
- }
-
- return true;
-}
-
-static bool
-coverage_statistics_has_stale_cache(GjsCoverage *coverage)
-{
- GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage);
- JSContext *js_context = (JSContext *) gjs_context_get_native_context(priv->context);
-
- JSAutoRequest ar(js_context);
- JSAutoCompartment ac(js_context, priv->coverage_statistics);
- JS::RootedObject rooted_priv(js_context, priv->coverage_statistics);
- JS::RootedValue stale_cache_value(js_context);
- if (!JS_CallFunctionName(js_context, rooted_priv, "staleCache",
- JS::HandleValueArray::empty(),
- &stale_cache_value)) {
- gjs_log_exception(js_context);
- g_error("Failed to call into javascript to get stale cache value. This is a bug");
- }
-
- return stale_cache_value.toBoolean();
-}
-
static unsigned int _suppressed_coverage_messages_count = 0;
/**
@@ -1204,15 +982,6 @@ gjs_coverage_write_statistics(GjsCoverage *coverage)
g_strfreev(executed_coverage_files);
- const bool has_cache_path = priv->cache != NULL;
- const bool cache_is_stale = coverage_statistics_has_stale_cache(coverage);
-
- if (has_cache_path && cache_is_stale) {
- GBytes *cache_data = gjs_serialize_statistics(coverage);
- gjs_write_cache_file(priv->cache, cache_data);
- g_bytes_unref(cache_data);
- }
-
char *output_file_path = g_file_get_path(priv->output_dir);
g_message("Wrote coverage statistics to %s", output_file_path);
if (_suppressed_coverage_messages_count) {
@@ -1292,67 +1061,6 @@ get_file_from_call_args_filename(JSContext *context,
}
static bool
-coverage_get_file_modification_time(JSContext *context,
- unsigned argc,
- JS::Value *vp)
-{
- JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
- GTimeVal mtime;
- bool ret = false;
- GFile *file = get_file_from_call_args_filename(context, args);
-
- if (!file)
- return false;
-
- if (gjs_get_file_mtime(file, &mtime)) {
- JS::AutoValueArray<2> mtime_values_array(context);
- mtime_values_array[0].setInt32(mtime.tv_sec);
- mtime_values_array[1].setInt32(mtime.tv_usec);
- JS::RootedObject array_obj(context,
- JS_NewArrayObject(context, mtime_values_array));
- if (!array_obj)
- goto out;
- args.rval().setObject(*array_obj);
- } else {
- args.rval().setNull();
- }
-
- ret = true;
-
-out:
- g_object_unref(file);
- return ret;
-}
-
-static bool
-coverage_get_file_checksum(JSContext *context,
- unsigned argc,
- JS::Value *vp)
-{
- JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
- GFile *file = get_file_from_call_args_filename(context, args);
-
- if (!file)
- return false;
-
- char *checksum = gjs_get_file_checksum(file);
-
- if (!checksum) {
- char *filename = get_file_identifier(file);
- gjs_throw(context, "Failed to read %s and get its checksum", filename);
- g_free(filename);
- g_object_unref(file);
- return false;
- }
-
- args.rval().setString(JS_NewStringCopyZ(context, checksum));
-
- g_object_unref(file);
- g_free(checksum);
- return true;
-}
-
-static bool
coverage_get_file_contents(JSContext *context,
unsigned argc,
JS::Value *vp)
@@ -1393,8 +1101,6 @@ coverage_get_file_contents(JSContext *context,
static JSFunctionSpec coverage_funcs[] = {
JS_FS("log", coverage_log, 1, GJS_MODULE_PROP_FLAGS),
JS_FS("getFileContents", coverage_get_file_contents, 1, GJS_MODULE_PROP_FLAGS),
- JS_FS("getFileModificationTime", coverage_get_file_modification_time, 1, GJS_MODULE_PROP_FLAGS),
- JS_FS("getFileChecksum", coverage_get_file_checksum, 1, GJS_MODULE_PROP_FLAGS),
JS_FS_END
};
@@ -1408,59 +1114,10 @@ coverage_statistics_tracer(JSTracer *trc, void *data)
"coverage_statistics");
}
-/* This function is mainly used in the tests in order to fiddle with
- * the internals of the coverage statisics collector on the coverage
- * compartment side */
-bool
-gjs_run_script_in_coverage_compartment(GjsCoverage *coverage,
- const char *script)
-{
- GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage);
- JSContext *js_context = (JSContext *) gjs_context_get_native_context(priv->context);
- JSAutoCompartment ac(js_context, priv->coverage_statistics);
- JSAutoRequest ar(js_context);
-
- JS::CompileOptions options(js_context);
- options.setUTF8(true);
-
- JS::RootedValue rval(js_context);
- if (!JS::Evaluate(js_context, options, script, strlen(script), &rval)) {
- gjs_log_exception(js_context);
- g_warning("Failed to evaluate <coverage_modifier>");
- return false;
- }
-
- return true;
-}
-
-bool
-gjs_inject_value_into_coverage_compartment(GjsCoverage *coverage,
- JS::HandleValue value,
- const char *property)
-{
- GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage);
-
- JSContext *js_context = (JSContext *) gjs_context_get_native_context(priv->context);
- JSAutoRequest ar(js_context);
- JSAutoCompartment ac(js_context, priv->coverage_statistics);
-
- JS::RootedObject coverage_global_scope(js_context,
- JS_GetGlobalForObject(js_context, priv->coverage_statistics));
-
- if (!JS_SetProperty(js_context, coverage_global_scope, property,
- value)) {
- g_warning("Failed to set property %s to requested value", property);
- return false;
- }
-
- return true;
-}
-
static bool
bootstrap_coverage(GjsCoverage *coverage)
{
GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage);
- GBytes *cache_bytes = NULL;
JSContext *context = (JSContext *) gjs_context_get_native_context(priv->context);
JSAutoRequest ar(context);
@@ -1493,28 +1150,11 @@ bootstrap_coverage(GjsCoverage *coverage)
&coverage_statistics_constructor))
return false;
- /* Create value for holding the cache. This will be undefined if
- * the cache does not exist, otherwise it will be an object set
- * to the value of the cache */
- JS::RootedValue cache_value(context);
-
- if (priv->cache)
- cache_bytes = read_all_bytes_from_file(priv->cache);
-
- if (cache_bytes) {
- JSString *cache_object = gjs_deserialize_cache_to_object_for_compartment(context,
- debugger_compartment,
- cache_bytes);
- cache_value.setString(cache_object);
- g_bytes_unref(cache_bytes);
- }
-
/* Now create the array to pass the desired prefixes over */
JSObject *prefixes = gjs_build_string_array(context, -1, priv->prefixes);
- JS::AutoValueArray<2> coverage_statistics_constructor_args(context);
+ JS::AutoValueArray<1> coverage_statistics_constructor_args(context);
coverage_statistics_constructor_args[0].setObject(*prefixes);
- coverage_statistics_constructor_args[1].set(cache_value);
JSObject *coverage_statistics = JS_New(context,
coverage_statistics_constructor,
@@ -1543,11 +1183,6 @@ gjs_coverage_constructed(GObject *object)
GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage);
new (&priv->coverage_statistics) JS::Heap<JSObject *>();
- if (!priv->cache_specified) {
- g_message("Cache path was not given, picking default one");
- priv->cache = g_file_new_for_path(".internal-gjs-coverage-cache");
- }
-
if (!bootstrap_coverage(coverage)) {
JSContext *context = static_cast<JSContext *>(gjs_context_get_native_context(priv->context));
JSAutoCompartment compartment(context, gjs_get_import_global(context));
@@ -1571,11 +1206,6 @@ gjs_coverage_set_property(GObject *object,
case PROP_CONTEXT:
priv->context = GJS_CONTEXT(g_value_dup_object(value));
break;
- case PROP_CACHE:
- priv->cache_specified = true;
- /* g_value_dup_object() adds a reference if not NULL */
- priv->cache = static_cast<GFile *>(g_value_dup_object(value));
- break;
case PROP_OUTPUT_DIRECTORY:
priv->output_dir = G_FILE(g_value_dup_object(value));
break;
@@ -1634,7 +1264,6 @@ gjs_coverage_finalize (GObject *object)
g_strfreev(priv->prefixes);
g_clear_object(&priv->output_dir);
- g_clear_object(&priv->cache);
priv->coverage_statistics.~Heap();
G_OBJECT_CLASS(gjs_coverage_parent_class)->finalize(object);
@@ -1660,11 +1289,6 @@ gjs_coverage_class_init (GjsCoverageClass *klass)
"A context to gather coverage stats for",
GJS_TYPE_CONTEXT,
(GParamFlags) (G_PARAM_CONSTRUCT_ONLY |
G_PARAM_WRITABLE));
- properties[PROP_CACHE] = g_param_spec_object("cache",
- "Cache",
- "File containing a cache to preload ASTs from",
- G_TYPE_FILE,
- (GParamFlags) (G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
properties[PROP_OUTPUT_DIRECTORY] =
g_param_spec_object("output-directory", "Output directory",
"Directory handle at which to output coverage statistics",
@@ -1708,28 +1332,3 @@ gjs_coverage_new (const char * const *prefixes,
return coverage;
}
-
-GjsCoverage *
-gjs_coverage_new_internal_with_cache(const char * const *coverage_prefixes,
- GjsContext *context,
- GFile *output_dir,
- GFile *cache)
-{
- GjsCoverage *coverage =
- GJS_COVERAGE(g_object_new(GJS_TYPE_COVERAGE,
- "prefixes", coverage_prefixes,
- "context", context,
- "cache", cache,
- "output-directory", output_dir,
- NULL));
-
- return coverage;
-}
-
-GjsCoverage *
-gjs_coverage_new_internal_without_cache(const char * const *prefixes,
- GjsContext *cx,
- GFile *output_dir)
-{
- return gjs_coverage_new_internal_with_cache(prefixes, cx, output_dir, NULL);
-}
diff --git a/installed-tests/js/testCoverage.js b/installed-tests/js/testCoverage.js
index 2d5389d..ed3b801 100644
--- a/installed-tests/js/testCoverage.js
+++ b/installed-tests/js/testCoverage.js
@@ -358,10 +358,6 @@ describe('Coverage statistics container', function () {
beforeEach(function () {
Coverage.getFileContents =
jasmine.createSpy('getFileContents').and.callFake(f => MockFiles[f]);
- Coverage.getFileChecksum =
- jasmine.createSpy('getFileChecksum').and.returnValue('abcd');
- Coverage.getFileModificationTime =
- jasmine.createSpy('getFileModificationTime').and.returnValue([1, 2]);
container = new Coverage.CoverageStatisticsContainer(MockFilenames);
});
@@ -384,70 +380,4 @@ describe('Coverage statistics container', function () {
it('ignores a file in angle brackets (our convention for programmatic scripts)', function () {
expect(() => container.fetchStatistics('<script>')).not.toThrow();
});
-
- const MockCache = '{ \
- "filename": { \
- "mtime": [1, 2], \
- "checksum": null, \
- "branches": [ \
- { \
- "point": 4, \
- "exits": [5] \
- } \
- ] \
- } \
- }';
-
- describe('with cache', function () {
- let container;
- beforeEach(function () {
- spyOn(Coverage, '_analyzeBranchInfoFromReflection').and.callThrough();
- container = new Coverage.CoverageStatisticsContainer(MockFilenames,
- MockCache);
- });
-
- it('fetches counters from cache', function () {
- container.fetchStatistics('filename');
- expect(Coverage._analyzeBranchInfoFromReflection).not.toHaveBeenCalled();
- });
-
- it('fetches counters from reflection if missed', function () {
- container.fetchStatistics('uncached');
- expect(Coverage._analyzeBranchInfoFromReflection).toHaveBeenCalled();
- });
-
- it('cache is not stale if all hit', function () {
- container.fetchStatistics('filename');
- expect(container.staleCache()).toBeFalsy();
- });
-
- it('cache is stale if missed', function () {
- container.fetchStatistics('uncached');
- expect(container.staleCache()).toBeTruthy();
- });
- });
-
- describe('coverage counters from cache', function () {
- let container, statistics;
- let containerWithNoCaching, statisticsWithNoCaching;
- beforeEach(function () {
- container = new Coverage.CoverageStatisticsContainer(MockFilenames,
- MockCache);
- statistics = container.fetchStatistics('filename');
-
- containerWithNoCaching = new Coverage.CoverageStatisticsContainer(MockFilenames);
- statisticsWithNoCaching = containerWithNoCaching.fetchStatistics('filename');
- });
-
- it('have same branch exits as reflection', function () {
- /* Branch starts on line 4 */
- expect(statisticsWithNoCaching[4].exits[0].line)
- .toEqual(statistics[4].exits[0].line);
- });
-
- it('have same branch points as reflection', function () {
- expect(statisticsWithNoCaching[4].point)
- .toEqual(statistics[4].point);
- });
- });
});
diff --git a/modules/_bootstrap/coverage.js b/modules/_bootstrap/coverage.js
index cb6b7ab..87588f4 100644
--- a/modules/_bootstrap/coverage.js
+++ b/modules/_bootstrap/coverage.js
@@ -458,32 +458,6 @@ function _convertFunctionCountersToArray(functionCounters) {
return arrayReturn;
}
-/* Looks up filename in cache and fetches branch info
- * directly from the cache */
-function _fetchBranchInfoFromCache(filename, cache) {
- if (!cache)
- return null;
-
- if (Object.keys(cache).indexOf(filename) !== -1) {
- let cache_for_file = cache[filename];
-
- if (cache_for_file.mtime) {
- let mtime = getFileModificationTime(filename);
- if (mtime[0] != cache[filename].mtime[0] ||
- mtime[1] != cache[filename].mtime[1])
- return null;
- } else {
- let checksum = getFileChecksum(filename);
- if (checksum != cache[filename].checksum)
- return null;
- }
-
- return cache_for_file.branches;
- }
-
- return null;
-}
-
function _analyzeBranchInfoFromReflection(filename, contents) {
// Shebang is illegal character sequence to JS parser
if (contents.startsWith('#!'))
@@ -494,22 +468,15 @@ function _analyzeBranchInfoFromReflection(filename, contents) {
}
var CoverageStatisticsContainer = class {
- constructor(prefixes, cache) {
+ constructor(prefixes) {
/* Copy the files array, so that it can be re-used in the tests */
- this._cachedASTs = cache ? JSON.parse(cache) : null;
this._coveredFiles = new Map();
- this._cacheMisses = 0;
}
_createStatisticsFor(filename) {
let contents = getFileContents(filename);
let nLines = _getNumberOfLinesForScript(contents);
-
- let info = _fetchBranchInfoFromCache(filename, this._cachedASTs);
- if (info === null) {
- this._cacheMisses++;
- info = _analyzeBranchInfoFromReflection(filename, contents);
- }
+ let info = _analyzeBranchInfoFromReflection(filename, contents);
if (info === null)
throw new Error('Failed to parse and reflect file ' + filename);
@@ -531,27 +498,6 @@ var CoverageStatisticsContainer = class {
return info;
}
- stringify() {
- let cache_data = {};
- for (let [filename, branchCounters] of this._coveredFiles) {
- // Filter out undefined lines, since the index represents the
- // current line number on the file (see _incrementLineCounters())
- let branches = branchCounters.filter(c => c !== undefined)
- .map(({point, exits}) => ({
- point,
- exits: exits.map(({line}) => line),
- }));
-
- let mtime = getFileModificationTime(filename);
- cache_data[filename] = {
- mtime,
- checksum: mtime === null ? getFileChecksum(filename) : null,
- branches,
- };
- }
- return JSON.stringify(cache_data);
- }
-
getCoveredFiles() {
return [...this._coveredFiles.keys()];
}
@@ -560,10 +506,6 @@ var CoverageStatisticsContainer = class {
return this._ensureStatisticsFor(filename);
}
- staleCache() {
- return this._cacheMisses > 0;
- }
-
deleteStatistics(filename) {
this._coveredFiles.delete(filename);
}
@@ -575,8 +517,8 @@ var CoverageStatisticsContainer = class {
* It isn't possible to unit test this class because it depends on running
* Debugger which in turn depends on objects injected in from another compartment */
var CoverageStatistics = class {
- constructor(prefixes, cache) {
- let container = new CoverageStatisticsContainer(prefixes, cache);
+ constructor(prefixes) {
+ let container = new CoverageStatisticsContainer(prefixes);
this.container = container;
/* 'debuggee' comes from the invocation from
@@ -631,14 +573,6 @@ var CoverageStatistics = class {
return this.container.getCoveredFiles();
}
- staleCache() {
- return this.container.staleCache();
- }
-
- stringify() {
- return this.container.stringify();
- }
-
getExecutedLinesFor(filename) {
let scripts = this._findScriptsForFilename(filename);
let counters = [];
diff --git a/test/gjs-test-coverage.cpp b/test/gjs-test-coverage.cpp
index f898ca0..abe3886 100644
--- a/test/gjs-test-coverage.cpp
+++ b/test/gjs-test-coverage.cpp
@@ -29,18 +29,11 @@
#include <stdio.h>
#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <ftw.h>
-
#include <glib.h>
#include <gio/gio.h>
-#include <gio/gunixoutputstream.h>
#include <gjs/gjs.h>
#include "gjs/coverage.h"
-#include "gjs/coverage-internal.h"
-
#include "gjs-test-utils.h"
typedef struct _GjsCoverageFixture {
@@ -123,9 +116,8 @@ gjs_coverage_fixture_set_up(gpointer fixture_data,
};
fixture->context = gjs_context_new_with_search_path((char **) search_paths);
- fixture->coverage =
- gjs_coverage_new_internal_without_cache(coverage_paths, fixture->context,
- fixture->lcov_output_dir);
+ fixture->coverage = gjs_coverage_new(coverage_paths, fixture->context,
+ fixture->lcov_output_dir);
replace_file(fixture->tmp_js_script, js_script);
g_free(tmp_output_dir_name);
@@ -303,44 +295,6 @@ coverage_data_matches_values_for_key(const char *data,
return false;
}
-/* A simple wrapper around gjs_coverage_new */
-static GjsCoverage *
-create_coverage_for_script(GjsContext *context,
- GFile *script,
- GFile *output_dir)
-{
- char *script_path = get_script_identifier(script);
- char *coverage_scripts[] = {
- script_path,
- NULL
- };
-
- GjsCoverage *retval =
- gjs_coverage_new_internal_without_cache(coverage_scripts, context,
- output_dir);
- g_free(script_path);
- return retval;
-}
-
-static GjsCoverage *
-create_coverage_for_script_and_cache(GjsContext *context,
- GFile *cache,
- GFile *script,
- GFile *output_dir)
-{
- char *script_path = get_script_identifier(script);
- char *coverage_scripts[] = {
- script_path,
- NULL
- };
-
- GjsCoverage *retval =
- gjs_coverage_new_internal_with_cache(coverage_scripts, context,
- output_dir, cache);
- g_free(script_path);
- return retval;
-}
-
static void
test_covered_file_is_duplicated_into_output_if_resource(gpointer fixture_data,
gconstpointer user_data)
@@ -362,10 +316,8 @@ test_covered_file_is_duplicated_into_output_if_resource(gpointer fixture_da
};
fixture->context = gjs_context_new_with_search_path(search_paths);
- fixture->coverage =
- gjs_coverage_new_internal_without_cache(coverage_scripts,
- fixture->context,
- fixture->lcov_output_dir);
+ fixture->coverage = gjs_coverage_new(coverage_scripts, fixture->context,
+ fixture->lcov_output_dir);
gjs_context_eval_file(fixture->context,
mock_resource_filename,
@@ -508,10 +460,8 @@ test_expected_entry_not_written_for_nonexistent_file(gpointer fixture_data,
};
g_object_unref(fixture->coverage);
- fixture->coverage =
- gjs_coverage_new_internal_without_cache(coverage_paths,
- fixture->context,
- fixture->lcov_output_dir);
+ fixture->coverage = gjs_coverage_new(coverage_paths, fixture->context,
+ fixture->lcov_output_dir);
/* Temporarily disable fatal mask and silence warnings */
GLogLevelFlags old_flags = g_log_set_always_fatal((GLogLevelFlags) G_LOG_LEVEL_ERROR);
@@ -1268,9 +1218,8 @@ gjs_coverage_multiple_source_files_to_single_output_fixture_set_up(gpointer fixt
fixture->base_fixture.context = gjs_context_new_with_search_path(search_paths);
fixture->base_fixture.coverage =
- gjs_coverage_new_internal_without_cache(coverage_paths,
- fixture->base_fixture.context,
- fixture->base_fixture.lcov_output_dir);
+ gjs_coverage_new(coverage_paths, fixture->base_fixture.context,
+ fixture->base_fixture.lcov_output_dir);
g_free(output_path);
g_free(first_js_script_path);
@@ -1429,671 +1378,6 @@ test_correct_line_coverage_data_written_for_both_source_file_sectons(gpointer
g_free(coverage_data_contents);
}
-static GString *
-append_tuples_to_array_in_object_notation(GString *string,
- const char *tuple_contents_strv)
-{
- char *original_ptr = (char *) tuple_contents_strv;
- char *expected_tuple_contents = NULL;
- while ((expected_tuple_contents = strsep((char **) &tuple_contents_strv, ";")) != NULL) {
- if (!strlen(expected_tuple_contents))
- continue;
-
- if (expected_tuple_contents != original_ptr)
- g_string_append_printf(string, ",");
- g_string_append_printf(string, "{%s}", expected_tuple_contents);
- }
-
- return string;
-}
-
-static GString *
-format_expected_cache_object_notation(const char *mtimes,
- const char *hash,
- GFile *script,
- const char *expected_branches)
-{
- char *script_name = get_script_identifier(script);
- GString *string = g_string_new("");
- g_string_append_printf(string,
- "{\"%s\":{\"mtime\":%s,\"checksum\":%s,\"branches\":[",
- script_name,
- mtimes,
- hash);
- g_free(script_name);
- append_tuples_to_array_in_object_notation(string, expected_branches);
- g_string_append_printf(string, "]}}");
- return string;
-}
-
-typedef struct _GjsCoverageCacheObjectNotationTestTableData {
- const char *test_name;
- const char *script;
- const char *uri;
- const char *expected_branches;
-} GjsCoverageCacheObjectNotationTableTestData;
-
-static GBytes *
-serialize_ast_to_bytes(GjsCoverage *coverage,
- const char **coverage_paths)
-{
- return gjs_serialize_statistics(coverage);
-}
-
-static char *
-serialize_ast_to_object_notation(GjsCoverage *coverage,
- const char **coverage_paths)
-{
- /* Unfortunately, we need to pass in this paramater here since
- * the len parameter is not allow-none.
- *
- * The caller doesn't need to know about the length of the
- * data since it is only used for strcmp and the data is
- * NUL-terminated anyway. */
- gsize len = 0;
- return (char *)g_bytes_unref_to_data(serialize_ast_to_bytes(coverage, coverage_paths),
- &len);
-}
-
-static char *
-eval_file_for_ast_in_object_notation(GjsContext *context,
- GjsCoverage *coverage,
- GFile *script)
-{
- bool success = eval_script(context, script);
- g_assert_true(success);
-
- char *filename = g_file_get_path(script);
- const gchar *coverage_paths[] = {
- filename,
- NULL
- };
-
- char *retval = serialize_ast_to_object_notation(coverage, coverage_paths);
- g_free(filename);
- return retval;
-}
-
-static void
-test_coverage_cache_data_in_expected_format(gpointer fixture_data,
- gconstpointer user_data)
-{
- GjsCoverageFixture *fixture = (GjsCoverageFixture *) fixture_data;
- GjsCoverageCacheObjectNotationTableTestData *table_data = (GjsCoverageCacheObjectNotationTableTestData
*) user_data;
-
- replace_file(fixture->tmp_js_script, table_data->script);
- char *cache_in_object_notation = eval_file_for_ast_in_object_notation(fixture->context,
- fixture->coverage,
- fixture->tmp_js_script);
- g_assert(cache_in_object_notation != NULL);
-
- GTimeVal mtime;
- bool successfully_got_mtime = gjs_get_file_mtime(fixture->tmp_js_script, &mtime);
- g_assert_true(successfully_got_mtime);
-
- char *mtime_string = g_strdup_printf("[%li,%li]", mtime.tv_sec, mtime.tv_usec);
- GString *expected_cache_object_notation = format_expected_cache_object_notation(mtime_string,
- "null",
- fixture->tmp_js_script,
-
table_data->expected_branches);
-
- g_assert_cmpstr(cache_in_object_notation, ==, expected_cache_object_notation->str);
-
- g_string_free(expected_cache_object_notation, true);
- g_free(cache_in_object_notation);
- g_free(mtime_string);
-}
-
-static void
-test_coverage_cache_data_in_expected_format_resource(gpointer fixture_data,
- gconstpointer user_data)
-{
- GjsCoverageFixture *fixture = (GjsCoverageFixture *) fixture_data;
- GjsCoverageCacheObjectNotationTableTestData *table_data = (GjsCoverageCacheObjectNotationTableTestData
*) user_data;
-
- GFile *resource = g_file_new_for_uri(table_data->uri);
-
- char *hash_string_no_quotes = gjs_get_file_checksum(resource);
-
- char *hash_string = g_strdup_printf("\"%s\"", hash_string_no_quotes);
- g_free(hash_string_no_quotes);
-
- GString *expected_cache_object_notation = format_expected_cache_object_notation("null",
- hash_string,
- resource,
-
table_data->expected_branches);
-
- g_clear_object(&fixture->coverage);
- fixture->coverage = create_coverage_for_script(fixture->context, resource,
- fixture->tmp_output_dir);
- char *cache_in_object_notation = eval_file_for_ast_in_object_notation(fixture->context,
- fixture->coverage,
- resource);
- g_object_unref(resource);
-
- g_assert_cmpstr(cache_in_object_notation, ==, expected_cache_object_notation->str);
-
- g_string_free(expected_cache_object_notation, true);
- g_free(cache_in_object_notation);
- g_free(hash_string);
-}
-
-static char *
-generate_coverage_compartment_verify_script(GFile *coverage_script,
- const char *user_script)
-{
- char *coverage_script_filename = g_file_get_path(coverage_script);
- char *retval =
- g_strdup_printf("const covered_script_filename = '%s';\n"
- "function assertEquals(lhs, rhs) {\n"
- " if (lhs !== rhs)\n"
- " throw new Error('Assertion failure');\n"
- "}\n"
- "function assertArrayEquals(lhs, rhs) {\n"
- " assertEquals(lhs.length, rhs.length);\n"
- " for (let i = 0; i < lhs.length; i++)\n"
- " assertEquals(lhs[i], rhs[i]);\n"
- "}\n"
- "\n"
- "%s", coverage_script_filename, user_script);
- g_free(coverage_script_filename);
- return retval;
-}
-
-static void
-test_coverage_cache_as_js_object_has_branches_prop(void *fixture_data,
- const void *unused)
-{
- auto fixture = static_cast<GjsCoverageFixture *>(fixture_data);
- const char *script =
- "let i = 0;\n"
- "if (i) {\n"
- " i = 1;\n"
- "} else {\n"
- " i = 2;\n"
- "}\n";
-
- replace_file(fixture->tmp_js_script, script);
- eval_script(fixture->context, fixture->tmp_js_script);
-
- char *script_filename = g_file_get_path(fixture->tmp_js_script);
- const gchar *coverage_paths[] = {
- script_filename,
- NULL
- };
-
- GBytes *cache = serialize_ast_to_bytes(fixture->coverage, coverage_paths);
- auto cx = static_cast<JSContext *>(gjs_context_get_native_context(fixture->context));
- JS::RootedValue cache_result_value(cx,
- JS::StringValue(gjs_deserialize_cache_to_object(fixture->coverage, cache)));
- gjs_inject_value_into_coverage_compartment(fixture->coverage,
- cache_result_value,
- "coverage_cache");
-
- const char *verify_script =
- "assertEquals(2, JSON.parse(coverage_cache)[covered_script_filename].branches[0].point);\n"
- "assertArrayEquals([3, 5],
JSON.parse(coverage_cache)[covered_script_filename].branches[0].exits);\n";
- char *verify_script_complete = generate_coverage_compartment_verify_script(fixture->tmp_js_script,
- verify_script);
- gjs_run_script_in_coverage_compartment(fixture->coverage,
- verify_script_complete);
- g_free(verify_script_complete);
- g_free(script_filename);
- g_bytes_unref(cache);
-}
-
-typedef struct _GjsCoverageCacheEqualResultsTableTestData {
- const char *test_name;
- const char *script;
-} GjsCoverageCacheEqualResultsTableTestData;
-
-
-static GFile *
-get_coverage_tmp_cache(void)
-{
- GFileIOStream *stream;
- GError *error = NULL;
- GFile *cache_file = g_file_new_tmp("gjs-coverage-cache-XXXXXX", &stream, &error);
- g_assert_no_error(error);
- g_assert_nonnull(cache_file);
- g_object_unref(stream);
-
- return cache_file;
-}
-
-static GFile *
-write_cache_to_temporary_file(GBytes *cache)
-{
- GFile *temporary_file = get_coverage_tmp_cache();
-
- if (!gjs_write_cache_file(temporary_file, cache)) {
- g_object_unref(temporary_file);
- return NULL;
- }
-
- return temporary_file;
-}
-
-static GFile *
-serialize_ast_to_cache_in_temporary_file(GjsCoverage *coverage,
- const char **coverage_paths)
-{
- GBytes *cache = serialize_ast_to_bytes(coverage, coverage_paths);
- GFile *cache_file = write_cache_to_temporary_file(cache);
-
- g_bytes_unref(cache);
-
- return cache_file;
-}
-
-static void
-test_coverage_cache_equal_results_to_reflect_parse(gpointer fixture_data,
- gconstpointer user_data)
-{
- GjsCoverageFixture *fixture = (GjsCoverageFixture *) fixture_data;
- GjsCoverageCacheEqualResultsTableTestData *equal_results_data =
(GjsCoverageCacheEqualResultsTableTestData *) user_data;
-
- replace_file(fixture->tmp_js_script, equal_results_data->script);
-
- char *tmp_js_script_filename = g_file_get_path(fixture->tmp_js_script);
- const gchar *coverage_paths[] = {
- tmp_js_script_filename,
- NULL
- };
-
- char *coverage_data_contents_no_cache =
- eval_script_and_get_coverage_data(fixture->context,
- fixture->coverage,
- fixture->tmp_js_script,
- fixture->lcov_output,
- NULL);
- GFile *cache_file = serialize_ast_to_cache_in_temporary_file(fixture->coverage,
- coverage_paths);
- g_assert_nonnull(cache_file);
-
- g_clear_object(&fixture->coverage);
- fixture->coverage = create_coverage_for_script_and_cache(fixture->context,
- cache_file,
- fixture->tmp_js_script,
- fixture->lcov_output_dir);
- g_object_unref(cache_file);
-
- /* Overwrite tracefile with nothing and start over */
- replace_file(fixture->lcov_output, "");
-
- char *coverage_data_contents_cached =
- eval_script_and_get_coverage_data(fixture->context,
- fixture->coverage,
- fixture->tmp_js_script,
- fixture->lcov_output,
- NULL);
-
- g_assert_cmpstr(coverage_data_contents_cached, ==, coverage_data_contents_no_cache);
-
- g_free(coverage_data_contents_cached);
- g_free(coverage_data_contents_no_cache);
- g_free(tmp_js_script_filename);
-}
-
-static GFile *
-eval_file_for_tmp_ast_cache(GjsContext *context,
- GjsCoverage *coverage,
- GFile *script)
-{
- bool success = eval_script(context, script);
- g_assert_true(success);
-
- char *filename = g_file_get_path(script);
- const gchar *coverage_paths[] = {
- filename,
- NULL
- };
-
- GFile *retval = serialize_ast_to_cache_in_temporary_file(coverage,
- coverage_paths);
- g_free(filename);
- return retval;
-}
-
-static void
-rewind_file_mtime(GFile *file)
-{
- GjsAutoUnref<GFileInfo> info = g_file_query_info(file,
- G_FILE_ATTRIBUTE_TIME_MODIFIED,
- G_FILE_QUERY_INFO_NONE,
- nullptr, nullptr);
- g_assert_nonnull(info);
-
- GTimeVal mtime;
- g_file_info_get_modification_time(info, &mtime);
-
- g_assert_cmpint(mtime.tv_sec, >, 0);
- mtime.tv_sec--;
- g_file_info_set_modification_time(info, &mtime);
-
- gboolean ok = g_file_set_attributes_from_info(file, info,
- G_FILE_QUERY_INFO_NONE,
- nullptr, nullptr);
- g_assert_true(ok);
-}
-
-/* Effectively, the results should be what we expect even though
- * we overwrote the original script after getting coverage and
- * fetching the cache */
-static void
-test_coverage_cache_invalidation(gpointer fixture_data,
- gconstpointer user_data)
-{
- GjsCoverageFixture *fixture = (GjsCoverageFixture *) fixture_data;
-
- GFile *cache_file = eval_file_for_tmp_ast_cache(fixture->context,
- fixture->coverage,
- fixture->tmp_js_script);
-
- rewind_file_mtime(cache_file);
-
- /* Overwrite tracefile with nothing */
- replace_file(fixture->lcov_output, "");
-
- /* Write a new script into the temporary js file, which will be
- * completely different to the original script that was there */
- replace_file(fixture->tmp_js_script,
- "let i = 0;\n"
- "let j = 0;\n");
-
- g_clear_object(&fixture->coverage);
- fixture->coverage = create_coverage_for_script_and_cache(fixture->context,
- cache_file,
- fixture->tmp_js_script,
- fixture->lcov_output_dir);
- g_object_unref(cache_file);
-
- gsize coverage_data_len = 0;
- char *coverage_data_contents =
- eval_script_and_get_coverage_data(fixture->context,
- fixture->coverage,
- fixture->tmp_js_script,
- fixture->lcov_output,
- &coverage_data_len);
-
- LineCountIsMoreThanData matchers[] =
- {
- {
- 1,
- 0
- },
- {
- 2,
- 0
- }
- };
-
- char *script_output_path = get_output_path_for_script_on_disk(fixture->tmp_js_script,
- fixture->lcov_output_dir);
-
- ExpectedSourceFileCoverageData expected[] = {
- {
- script_output_path,
- matchers,
- 2,
- '2',
- '2'
- }
- };
-
- const gsize expected_len = G_N_ELEMENTS(expected);
- const char *record = line_starting_with(coverage_data_contents, "SF:");
- g_assert_nonnull(record);
- g_assert(check_coverage_data_for_source_file(expected, expected_len, record));
-
- g_free(script_output_path);
- g_free(coverage_data_contents);
-}
-
-static void
-unload_resource(GResource *resource)
-{
- g_resources_unregister(resource);
- g_resource_unref(resource);
-}
-
-static GResource *
-load_resource_from_builddir(const char *name)
-{
- char *resource_path = g_build_filename(GJS_TOP_BUILDDIR,
- name,
- NULL);
-
- GError *error = NULL;
- GResource *resource = g_resource_load(resource_path,
- &error);
-
- g_assert_no_error(error);
- g_resources_register(resource);
-
- g_free(resource_path);
-
- return resource;
-}
-
-/* Load first resource, then unload and load second resource. Both have
- * the same path, but different contents */
-static void
-test_coverage_cache_invalidation_resource(gpointer fixture_data,
- gconstpointer user_data)
-{
- GjsCoverageFixture *fixture = (GjsCoverageFixture *) fixture_data;
-
- GFile *mock_resource = g_file_new_for_uri("resource:///org/gnome/gjs/mock/cache/resource.js");
-
- /* Load the resource archive and register it */
- GResource *first_resource = load_resource_from_builddir("mock-cache-invalidation-before.gresource");
-
- g_clear_object(&fixture->coverage);
- fixture->coverage = create_coverage_for_script(fixture->context,
- mock_resource,
- fixture->lcov_output_dir);
-
- GFile *cache_file = eval_file_for_tmp_ast_cache(fixture->context,
- fixture->coverage,
- mock_resource);
-
- /* Load the "after" resource, but have the exact same coverage paths */
- unload_resource(first_resource);
- GResource *second_resource = load_resource_from_builddir("mock-cache-invalidation-after.gresource");
-
- /* Overwrite tracefile with nothing */
- replace_file(fixture->lcov_output, "");
-
- g_clear_object(&fixture->coverage);
- fixture->coverage = create_coverage_for_script_and_cache(fixture->context,
- cache_file,
- mock_resource,
- fixture->lcov_output_dir);
- g_object_unref(cache_file);
-
- char *coverage_data_contents =
- eval_script_and_get_coverage_data(fixture->context, fixture->coverage,
- mock_resource, fixture->lcov_output,
- NULL);
-
- /* Don't need this anymore */
- g_object_unref(mock_resource);
- unload_resource(second_resource);
-
- /* Now assert that the coverage file has executable lines in
- * the places that we expect them to be */
- LineCountIsMoreThanData matchers[] = {
- {
- 1,
- 0
- },
- {
- 2,
- 0
- }
- };
-
- GFile *output_script =
- g_file_resolve_relative_path(fixture->lcov_output_dir,
- "org/gnome/gjs/mock/cache/resource.js");
- char *script_output_path = g_file_get_path(output_script);
- g_object_unref(output_script);
-
- ExpectedSourceFileCoverageData expected[] = {
- {
- script_output_path,
- matchers,
- 2,
- '2',
- '2'
- }
- };
-
- const gsize expected_len = G_N_ELEMENTS(expected);
- const char *record = line_starting_with(coverage_data_contents, "SF:");
- g_assert(check_coverage_data_for_source_file(expected, expected_len, record));
-
- g_free(script_output_path);
- g_free(coverage_data_contents);
-}
-
-static void
-test_coverage_cache_file_written_when_no_cache_exists(gpointer fixture_data,
- gconstpointer user_data)
-{
- GjsCoverageFixture *fixture = (GjsCoverageFixture *) fixture_data;
- GFile *cache_file = get_coverage_tmp_cache();
-
- g_clear_object(&fixture->coverage);
- fixture->coverage = create_coverage_for_script_and_cache(fixture->context,
- cache_file,
- fixture->tmp_js_script,
- fixture->lcov_output_dir);
-
- /* We need to execute the script now in order for a cache entry
- * to be created, since unexecuted scripts are not counted as
- * part of the coverage report. */
- bool success = eval_script(fixture->context, fixture->tmp_js_script);
- g_assert_true(success);
-
- gjs_coverage_write_statistics(fixture->coverage);
-
- g_assert_true(g_file_query_exists(cache_file, NULL));
- g_object_unref(cache_file);
-}
-
-static GTimeVal
-eval_script_for_cache_mtime(GjsContext *context,
- GjsCoverage *coverage,
- GFile *cache_file,
- GFile *script)
-{
- bool success = eval_script(context, script);
- g_assert_true(success);
-
- gjs_coverage_write_statistics(coverage);
-
- GTimeVal mtime;
- bool successfully_got_mtime = gjs_get_file_mtime(cache_file, &mtime);
- g_assert_true(successfully_got_mtime);
-
- return mtime;
-}
-
-static void
-test_coverage_cache_updated_when_cache_stale(gpointer fixture_data,
- gconstpointer user_data)
-{
- GjsCoverageFixture *fixture = (GjsCoverageFixture *) fixture_data;
-
- GFile *cache_file = get_coverage_tmp_cache();
- g_clear_object(&fixture->coverage);
- fixture->coverage = create_coverage_for_script_and_cache(fixture->context,
- cache_file,
- fixture->tmp_js_script,
- fixture->lcov_output_dir);
-
- GTimeVal first_cache_mtime = eval_script_for_cache_mtime(fixture->context,
- fixture->coverage,
- cache_file,
- fixture->tmp_js_script);
-
- rewind_file_mtime(cache_file);
-
- /* Write a new script into the temporary js file, which will be
- * completely different to the original script that was there */
- replace_file(fixture->tmp_js_script,
- "let i = 0;\n"
- "let j = 0;\n");
-
- /* Re-create coverage object, covering new script */
- g_clear_object(&fixture->coverage);
- fixture->coverage = create_coverage_for_script_and_cache(fixture->context,
- cache_file,
- fixture->tmp_js_script,
- fixture->lcov_output_dir);
-
-
- /* Run the script again, which will cause an attempt
- * to look up the AST data. Upon writing the statistics
- * again, the cache should have been missed some of the time
- * so the second mtime will be greater than the first */
- GTimeVal second_cache_mtime = eval_script_for_cache_mtime(fixture->context,
- fixture->coverage,
- cache_file,
- fixture->tmp_js_script);
-
-
- const bool seconds_different = (first_cache_mtime.tv_sec != second_cache_mtime.tv_sec);
- const bool microseconds_different = (first_cache_mtime.tv_usec != second_cache_mtime.tv_usec);
-
- g_assert_true(seconds_different || microseconds_different);
-
- g_object_unref(cache_file);
-}
-
-static void
-test_coverage_cache_not_updated_on_full_hits(gpointer fixture_data,
- gconstpointer user_data)
-{
- GjsCoverageFixture *fixture = (GjsCoverageFixture *) fixture_data;
-
- GFile *cache_file = get_coverage_tmp_cache();
- g_clear_object(&fixture->coverage);
- fixture->coverage = create_coverage_for_script_and_cache(fixture->context,
- cache_file,
- fixture->tmp_js_script,
- fixture->lcov_output_dir);
-
- GTimeVal first_cache_mtime = eval_script_for_cache_mtime(fixture->context,
- fixture->coverage,
- cache_file,
- fixture->tmp_js_script);
-
- /* Re-create coverage object, covering same script */
- g_clear_object(&fixture->coverage);
- fixture->coverage = create_coverage_for_script_and_cache(fixture->context,
- cache_file,
- fixture->tmp_js_script,
- fixture->lcov_output_dir);
-
-
- /* Run the script again, which will cause an attempt
- * to look up the AST data. Upon writing the statistics
- * again, the cache should have been hit of the time
- * so the second mtime will be the same as the first */
- GTimeVal second_cache_mtime = eval_script_for_cache_mtime(fixture->context,
- fixture->coverage,
- cache_file,
- fixture->tmp_js_script);
-
- g_assert_cmpint(first_cache_mtime.tv_sec, ==, second_cache_mtime.tv_sec);
- g_assert_cmpint(first_cache_mtime.tv_usec, ==, second_cache_mtime.tv_usec);
-
- g_object_unref(cache_file);
-}
-
typedef struct _FixturedTest {
gsize fixture_size;
GTestFixtureFunc set_up;
@@ -2114,41 +1398,6 @@ add_test_for_fixture(const char *name,
fixture->tear_down);
}
-/* All table driven tests must be binary compatible with at
- * least this header */
-typedef struct _TestTableDataHeader {
- const char *test_name;
-} TestTableDataHeader;
-
-static void
-add_table_driven_test_for_fixture(const char *name,
- FixturedTest *fixture,
- GTestFixtureFunc test_func,
- gsize table_entry_size,
- gsize n_table_entries,
- const TestTableDataHeader *test_table)
-{
- const char *test_table_ptr = (const char *)test_table;
- gsize test_table_index;
-
- for (test_table_index = 0;
- test_table_index < n_table_entries;
- ++test_table_index, test_table_ptr += table_entry_size) {
- const TestTableDataHeader *header =
- reinterpret_cast<const TestTableDataHeader *>(test_table_ptr);
- gchar *test_name_for_table_index = g_strdup_printf("%s/%s",
- name,
- header->test_name);
- g_test_add_vtable(test_name_for_table_index,
- fixture->fixture_size,
- test_table_ptr,
- fixture->set_up,
- test_func,
- fixture->tear_down);
- g_free(test_name_for_table_index);
- }
-}
-
void gjs_test_add_tests_for_coverage()
{
FixturedTest coverage_fixture = {
@@ -2256,105 +1505,4 @@ void gjs_test_add_tests_for_coverage()
&coverage_for_multiple_files_to_single_output_fixture,
test_correct_line_coverage_data_written_for_both_source_file_sectons,
NULL);
-
- /* This must be static, because g_test_add_vtable does not copy it */
- static GjsCoverageCacheObjectNotationTableTestData data_in_expected_format_table[] = {
- {
- "simple_executable_lines",
- "let i = 0;\n",
- "resource://org/gnome/gjs/mock/test/gjs-test-coverage/cache_notation/simple_executable_lines.js",
- ""
- },
- {
- "simple_branch",
- "let i = 0;\n"
- "if (i) {\n"
- " i = 1;\n"
- "} else {\n"
- " i = 2;\n"
- "}\n",
- "resource://org/gnome/gjs/mock/test/gjs-test-coverage/cache_notation/simple_branch.js",
- "\"point\":2,\"exits\":[3,5]"
- },
- {
- "simple_function",
- "function f() {\n"
- "}\n",
- "resource://org/gnome/gjs/mock/test/gjs-test-coverage/cache_notation/simple_function.js",
- ""
- }
- };
-
- add_table_driven_test_for_fixture("/gjs/coverage/cache/data_format",
- &coverage_fixture,
- test_coverage_cache_data_in_expected_format,
- sizeof(GjsCoverageCacheObjectNotationTableTestData),
- G_N_ELEMENTS(data_in_expected_format_table),
- (const TestTableDataHeader *) data_in_expected_format_table);
-
- add_table_driven_test_for_fixture("/gjs/coverage/cache/data_format_resource",
- &coverage_fixture,
- test_coverage_cache_data_in_expected_format_resource,
- sizeof(GjsCoverageCacheObjectNotationTableTestData),
- G_N_ELEMENTS(data_in_expected_format_table),
- (const TestTableDataHeader *) data_in_expected_format_table);
-
- add_test_for_fixture("/gjs/coverage/cache/object_branches_prop",
- &coverage_fixture,
- test_coverage_cache_as_js_object_has_branches_prop,
- NULL);
-
- static GjsCoverageCacheEqualResultsTableTestData equal_results_table[] = {
- {
- "simple_executable_lines",
- "let i = 0;\n"
- "let j = 1;\n"
- },
- {
- "simple_branch",
- "let i = 0;\n"
- "if (i) {\n"
- " i = 1;\n"
- "} else {\n"
- " i = 2;\n"
- "}\n"
- },
- {
- "simple_function",
- "function f() {\n"
- "}\n"
- }
- };
-
- add_table_driven_test_for_fixture("/gjs/coverage/cache/equal/executable_lines",
- &coverage_fixture,
- test_coverage_cache_equal_results_to_reflect_parse,
- sizeof(GjsCoverageCacheEqualResultsTableTestData),
- G_N_ELEMENTS(equal_results_table),
- (const TestTableDataHeader *) equal_results_table);
-
- add_test_for_fixture("/gjs/coverage/cache/invalidation",
- &coverage_fixture,
- test_coverage_cache_invalidation,
- NULL);
-
- add_test_for_fixture("/gjs/coverage/cache/invalidation_resource",
- &coverage_fixture,
- test_coverage_cache_invalidation_resource,
- NULL);
-
- add_test_for_fixture("/gjs/coverage/cache/file_written",
- &coverage_fixture,
- test_coverage_cache_file_written_when_no_cache_exists,
- NULL);
-
- add_test_for_fixture("/gjs/coverage/cache/no_update_on_full_hits",
- &coverage_fixture,
- test_coverage_cache_not_updated_on_full_hits,
- NULL);
-
- add_test_for_fixture("/gjs/coverage/cache/update_on_misses",
- &coverage_fixture,
- test_coverage_cache_updated_when_cache_stale,
- NULL);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]