Repository: google/clusterfuzz

Issue:
Default values for strategy stats in BigQuery
We used to initialize all strategy columns with 0, but we don't seem to be doing it now, e.g.:

```sql
SELECT
  count(1)
FROM
  `libFuzzer_stats.TestcaseRun`
WHERE
  strategy_dataflow_tracing = 0
  AND timestamp >= 1576195200 /* Dec 13th 00:00 UTC */
  AND timestamp <= 1577059200 /* Dec 23th 00:00 UTC */
```

returns `0`, while

```sql
...
  strategy_dataflow_tracing = 1
...
```

makes it `2,345`, and

```sql
...
  strategy_dataflow_tracing IS NULL
...
```

makes it a large number as well.

Same for e.g. `  strategy_recommended_dict = 0` and likely other strategies.

IMO this is not a big deal, but I'd prefer a default value instead of `NULL`, as it simplifies query writing plus `NULL` works as an indicator that a particular strategy wasn't supported at all. Right now it's indistinguishable whether we do not support a strategy or it just isn't being used.

This also might be the reason why Data Studio charts aren't working //cc @mbarbella-chromium 


Discussion:
Marty, can you fix this and dataflow graphs.

Resolving patch:
diff --git a/src/python/bot/fuzzers/libFuzzer/engine.py b/src/python/bot/fuzzers/libFuzzer/engine.py
--- a/src/python/bot/fuzzers/libFuzzer/engine.py
+++ b/src/python/bot/fuzzers/libFuzzer/engine.py
@@ -289,11 +289,8 @@ def fuzz(self, target_path, options, reproducers_dir, max_time):
 
     # Extend parsed stats by additional performance features.
     parsed_stats.update(
-        stats.parse_performance_features(
-            log_lines,
-            options.strategies,
-            options.arguments,
-            include_strategies=False))
+        stats.parse_performance_features(log_lines, options.strategies,
+                                         options.arguments))
 
     # Set some initial stat overrides.
     timeout_limit = fuzzer_utils.extract_argument(
diff --git a/src/python/bot/fuzzers/libFuzzer/stats.py b/src/python/bot/fuzzers/libFuzzer/stats.py
--- a/src/python/bot/fuzzers/libFuzzer/stats.py
+++ b/src/python/bot/fuzzers/libFuzzer/stats.py
@@ -160,10 +160,7 @@ def parse_line_for_strategy_prefix(line, strategy_name):
   return stats
 
 
-def parse_performance_features(log_lines,
-                               strategies,
-                               arguments,
-                               include_strategies=True):
+def parse_performance_features(log_lines, strategies, arguments):
   """Extract stats for performance analysis."""
   # TODO(ochang): Remove include_strategies once refactor is complete.
   # Initialize stats with default values.
@@ -200,13 +197,12 @@ def parse_performance_features(log_lines,
   stats['strategy_selection_method'] = environment.get_value(
       'STRATEGY_SELECTION_METHOD', default_value='default')
 
-  if include_strategies:
-    # Initialize all strategy stats as disabled by default.
-    for strategy_type in strategy.LIBFUZZER_STRATEGY_LIST:
-      stats[strategy_column_name(strategy_type.name)] = 0
+  # Initialize all strategy stats as disabled by default.
+  for strategy_type in strategy.LIBFUZZER_STRATEGY_LIST:
+    stats[strategy_column_name(strategy_type.name)] = 0
 
-    # Process fuzzing strategies used.
-    stats.update(parse_fuzzing_strategies(log_lines, strategies))
+  # Process fuzzing strategies used.
+  stats.update(parse_fuzzing_strategies(log_lines, strategies))
 
   (stats['log_lines_unwanted'], stats['log_lines_from_engine'],
    stats['log_lines_ignored']) = calculate_log_lines(log_lines)


Test patch:
diff --git a/src/python/tests/core/bot/fuzzers/libFuzzer/engine_test.py b/src/python/tests/core/bot/fuzzers/libFuzzer/engine_test.py
--- a/src/python/tests/core/bot/fuzzers/libFuzzer/engine_test.py
+++ b/src/python/tests/core/bot/fuzzers/libFuzzer/engine_test.py
@@ -336,9 +336,18 @@ def mock_merge(*args, **kwargs):  # pylint: disable=unused-argument
         'slow_units_count': 0,
         'slowest_unit_time_sec': 0,
         'startup_crash_count': 0,
+        'strategy_corpus_mutations_ml_rnn': 0,
+        'strategy_corpus_mutations_radamsa': 0,
+        'strategy_corpus_subset': 0,
+        'strategy_dataflow_tracing': 0,
+        'strategy_fork': 0,
+        'strategy_mutator_plugin': 0,
+        'strategy_random_max_len': 0,
+        'strategy_recommended_dict': 0,
+        'strategy_selection_method': 'default',
+        'strategy_value_profile': 0,
         'timeout_count': 0,
         'timeout_limit': 123,
-        'strategy_selection_method': 'default',
     }, result.stats)