blob: c95e5f3adf617a8fa7a1d4172a692fd88d304df8 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TOOLS_TRAFFIC_ANNOTATION_AUDITOR_TRAFFIC_ANNOTATION_AUDITOR_H_
#define TOOLS_TRAFFIC_ANNOTATION_AUDITOR_TRAFFIC_ANNOTATION_AUDITOR_H_
#include <vector>
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "tools/traffic_annotation/auditor/auditor_result.h"
#include "tools/traffic_annotation/auditor/instance.h"
#include "tools/traffic_annotation/auditor/traffic_annotation_exporter.h"
#include "tools/traffic_annotation/traffic_annotation.pb.h"
// Holds an item of safe list rules for auditor.
struct AuditorException {
enum class ExceptionType {
ALL, // Ignore all errors (doesn't check the files at all).
MISSING, // Ignore missing annotations.
DIRECT_ASSIGNMENT, // Ignore direct assignment of annotation value.
TEST_ANNOTATION, // Ignore usages of annotation for tests.
EXCEPTION_TYPE_LAST = TEST_ANNOTATION
} type;
static bool TypeFromString(const std::string& type_string,
ExceptionType* type_value) {
if (type_string == "all") {
*type_value = ExceptionType::ALL;
} else if (type_string == "missing") {
*type_value = ExceptionType::MISSING;
} else if (type_string == "direct_assignment") {
*type_value = ExceptionType::DIRECT_ASSIGNMENT;
} else if (type_string == "test_annotation") {
*type_value = ExceptionType::TEST_ANNOTATION;
} else {
return false;
}
return true;
}
};
class TrafficAnnotationAuditor {
public:
// Creates an auditor object, storing the following paths:
// |source_path|: Path to the src directory.
// |build_path|: Path to a compiled build directory.
// |clang_tool_path|: Path to the 'traffic_annotation_extractor' clang tool.
TrafficAnnotationAuditor(const base::FilePath& source_path,
const base::FilePath& build_path,
const base::FilePath& clang_tool_path);
~TrafficAnnotationAuditor();
// Runs traffic_annotation_extractor clang tool and puts its output in
// |clang_tool_raw_output_|. If |filter_files_based_on_heuristics| flag is
// set, the list of files will be received from repository and heuristically
// filtered to only process the relevant files. If |use_compile_commands| flag
// is set, the list of files is extracted from compile_commands.json instead
// of git and will not be filtered.
// If clang tool returns error, and |rerun_on_errors| is true, the tool is run
// again to record errors.
// Errors are written to |errors_file| if it is not empty, otherwise
// LOG(ERROR).
bool RunClangTool(const std::vector<std::string>& path_filters,
bool filter_files_based_on_heuristics,
bool use_compile_commands,
bool rerun_on_errors,
const base::FilePath& errors_file);
// Parses the output of clang tool (|clang_tool_raw_output_|) and populates
// |extracted_annotations_|, |extracted_calls_|, and |errors_|.
// Errors include not finding the file, incorrect content, or missing or not
// provided annotations.
bool ParseClangToolRawOutput();
// Computes the hash value of a traffic annotation unique id.
static int ComputeHashValue(const std::string& unique_id);
// Loads the safe list file and populates |safe_list_|.
bool LoadSafeList();
// Checks to see if a |file_path| matches a safe list with given type.
bool IsSafeListed(const std::string& file_path,
AuditorException::ExceptionType exception_type);
// Checks to see if annotation contents are valid. Complete annotations should
// have all required fields and be consistent, and incomplete annotations
// should be completed with each other. Merges all matching incomplete
// annotations and adds them to |extracted_annotations_|, adds errors
// to |errors| and purges all incomplete annotations.
void CheckAnnotationsContents();
// Checks to see if all functions that need annotations have one.
void CheckAllRequiredFunctionsAreAnnotated();
// Checks if a call instance can stay not annotated.
bool CheckIfCallCanBeUnannotated(const CallInstance& call);
// Performs all checks on extracted annotations and calls. The input path
// filters are passed so that the data for files that were not tested would be
// read from annotations.xml. If |report_xml_updates| is set and
// annotations.xml requires updates, the updates are added to |errors_|.
bool RunAllChecks(const std::vector<std::string>& path_filters,
bool report_xml_updates);
// Returns a mapping of reserved unique ids' hash codes to the unique ids'
// texts. This list includes all unique ids that are defined in
// net/traffic_annotation/network_traffic_annotation.h and
// net/traffic_annotation/network_traffic_annotation_test_helper.h
static const std::map<int, std::string>& GetReservedIDsMap();
// Returns a set of reserved unique ids' hash codes. This set includes all
// unique ids that are defined in
// net/traffic_annotation/network_traffic_annotation.h and
// net/traffic_annotation/network_traffic_annotation_test_helper.h
static std::set<int> GetReservedIDsSet();
std::string clang_tool_raw_output() const { return clang_tool_raw_output_; }
void set_clang_tool_raw_output(const std::string& raw_output) {
clang_tool_raw_output_ = raw_output;
}
const std::vector<AnnotationInstance>& extracted_annotations() const {
return extracted_annotations_;
}
void SetExtractedAnnotationsForTesting(
const std::vector<AnnotationInstance>& annotations) {
extracted_annotations_ = annotations;
}
void SetExtractedCallsForTesting(const std::vector<CallInstance>& calls) {
extracted_calls_ = calls;
}
const std::vector<CallInstance>& extracted_calls() const {
return extracted_calls_;
}
const std::vector<AuditorResult>& errors() const { return errors_; }
const TrafficAnnotationExporter& exporter() const { return exporter_; }
void ClearErrorsForTesting() { errors_.clear(); }
void ClearCheckedDependenciesForTesting() { checked_dependencies_.clear(); }
// Sets the path to a file that would be used to mock the output of
// 'gn refs --all [build directory] [file path]' in tests.
void SetGnFileForTesting(const base::FilePath& file_path) {
gn_file_for_test_ = file_path;
}
// Returns the path to clang internal libraries.
base::FilePath GetClangLibraryPath();
private:
const base::FilePath source_path_;
const base::FilePath build_path_;
const base::FilePath clang_tool_path_;
base::FilePath absolute_source_path_;
std::vector<std::string> clang_tool_switches_;
TrafficAnnotationExporter exporter_;
std::string clang_tool_raw_output_;
std::vector<AnnotationInstance> extracted_annotations_;
std::vector<CallInstance> extracted_calls_;
std::vector<AuditorResult> errors_;
bool safe_list_loaded_;
std::vector<std::string>
safe_list_[static_cast<int>(
AuditorException::ExceptionType::EXCEPTION_TYPE_LAST) +
1];
// Adds all archived annotations (from annotations.xml) that match the
// following features, to |extracted_annotations_|:
// 1- Not deprecated.
// 2- OS list includes current platform.
// 2- Has a path (is not a reserved word).
// 3- Path matches an item in |path_filters|.
void AddMissingAnnotations(const std::vector<std::string>& path_filters);
// Generates files list to Run clang tool on. Please refer to RunClangTool
// function's comment.
void GenerateFilesListForClangTool(
const std::vector<std::string>& path_filters,
bool filter_files_based_on_heuristics,
bool use_compile_commands,
std::vector<std::string>* file_paths);
base::FilePath gn_file_for_test_;
std::map<std::string, bool> checked_dependencies_;
};
#endif // TOOLS_TRAFFIC_ANNOTATION_AUDITOR_TRAFFIC_ANNOTATION_AUDITOR_H_