File: error_monitor.h

package info (click to toggle)
vulkan-validationlayers 1.4.321.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 47,412 kB
  • sloc: cpp: 594,175; python: 11,321; sh: 24; makefile: 20; xml: 14
file content (136 lines) | stat: -rw-r--r-- 5,918 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * Copyright (c) 2015-2025 The Khronos Group Inc.
 * Copyright (c) 2015-2025 Valve Corporation
 * Copyright (c) 2015-2025 LunarG, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <atomic>
#include <mutex>
#include <cassert>
#include <string>
#include <vector>

#include "error_message/log_message_type.h"
#include <vulkan/vulkan_core.h>

// ErrorMonitor Usage:
//
// Call SetDesiredFailureMsg with a string to be compared against all
// encountered log messages, or a validation error enum identifying
// desired error message. Passing NULL or VALIDATION_ERROR_MAX_ENUM
// will match all log messages. logMsg will return true for skipCall
// only if msg is matched or NULL.
//
// Call VerifyFound to determine if all desired failure messages
// were encountered. Call VerifyNotFound to determine if any unexpected
// failure was encountered.
class ErrorMonitor {
  public:
    ErrorMonitor(bool print_all_errors);
    ~ErrorMonitor() noexcept = default;

    void CreateCallback(VkInstance instance) noexcept;
    void DestroyCallback(VkInstance instance) noexcept;

    ErrorMonitor(const ErrorMonitor &) = delete;
    ErrorMonitor &operator=(const ErrorMonitor &) = delete;
    ErrorMonitor(ErrorMonitor &&) noexcept = delete;
    ErrorMonitor &operator=(ErrorMonitor &&) noexcept = delete;

    // Set monitor to pristine state
    void Reset();

    // ErrorMonitor will look for an error message containing the specified string(s)
    void SetDesiredFailureMsg(const VkFlags msg_flags, const char *const msg_string);
    void SetDesiredFailureMsg(const VkFlags msg_flags, const std::string &msg);
    void SetDesiredFailureMsgRegex(const VkFlags msg_flags, const char *vuid, std::string regex_str);
    // Any error message matching undesired_regex_str will provoke a test failure
    void SetDesiredFailureMsgRegex(const VkFlags msg_flags, const char *vuid, std::string regex_str,
                                   std::string undesired_regex_str);
    // Most tests check for kErrorBit so default to just using it
    void SetDesiredError(const char *msg, uint32_t count = 1);
    // Regex uses modified ECMAScript regular expression grammar https://eel.is/c++draft/re.grammar
    void SetDesiredErrorRegex(const char *vuid, std::string regex_str, uint32_t count = 1);
    // And use this for
    void SetDesiredWarningRegex(const char *vuid, std::string regex_str, uint32_t count = 1);
    void SetDesiredWarning(const char *msg, uint32_t count = 1);
    void SetDesiredInfo(const char *msg, uint32_t count = 1);

    // Set an error that the error monitor will ignore. Do not use this function if you are creating a new test.
    // TODO: This is stopgap to block new unexpected errors from being introduced. The long-term goal is to remove the use of this
    // function and its definition.
    void SetUnexpectedError(const char *const msg);

    // Set an error that should not cause a test failure
    void SetAllowedFailureMsg(const char *const msg);

    VkBool32 CheckForDesiredMsg(const char *vuid, const char *const msg_string);
    VkDebugReportFlagsEXT GetMessageFlags();
    void SetError(const char *const errorString);
    void SetBailout(std::atomic<bool> *bailout);

    // Helpers
    void VerifyFound();
    void Finish();

    const auto *GetDebugCreateInfo() const { return &debug_create_info_; }

    // ExpectSuccess now takes an optional argument allowing a custom combination of debug flags
    void ExpectSuccess(VkDebugReportFlagsEXT const message_flag_mask = kErrorBit);

  private:
    bool ExpectingSuccess() const;
    bool NeedCheckSuccess() const;
    void VerifyNotFound();
    // TODO: This is stopgap to block new unexpected errors from being introduced. The long-term goal is to remove the use of this
    // function and its definition.
    bool IgnoreMessage(std::string const &msg) const;
    bool AnyDesiredMsgFound() const;
    void MonitorReset();
    std::unique_lock<std::mutex> Lock() const { return std::unique_lock<std::mutex>(mutex_); }

    VkDebugUtilsMessengerEXT debug_obj_ = VK_NULL_HANDLE;
    VkDebugUtilsMessengerCreateInfoEXT debug_create_info_{};

    VkFlags message_flags_{};
    std::vector<std::string> failure_message_strings_;
    struct VuidAndMessage {
        std::string_view vuid;
        enum MsgType { Undefined, String, Regex } msg_type = Undefined;
        std::string msg_string;  // also used to store regex string
        std::string undesired_msg_regex_string;
        void SetMsgString(std::string msg) {
            msg_type = MsgType::String;
            msg_string = std::move(msg);
        }
        void SetMsgRegex(std::string regex_str) {
            msg_type = MsgType::Regex;
            msg_string = std::move(regex_str);
        }
        void SetUndesiredMsgRegex(std::string undesired_regex_str) { undesired_msg_regex_string = std::move(undesired_regex_str); }
        bool Search(const char *vuid, std::string_view msg) const;
        bool SearchUndesiredRegex(std::string_view msg) const;
        std::string Print() const;
    };
    std::vector<VuidAndMessage> desired_messages_;
    std::vector<VuidAndMessage> undesired_messages_;
    std::vector<std::string> ignore_message_strings_;
    std::vector<std::string> allowed_message_strings_;
    mutable std::mutex mutex_;
    std::atomic<bool> *bailout_{};
    bool message_found_{};
    bool print_all_errors_{};
};