Add check-namespace script (#6438)

This also fixes a lot of code files to be conforming to the script.

Co-authored-by: allejok96 <allejok96@gmail.com>
This commit is contained in:
Johannes Lorenz
2022-08-30 02:19:07 +02:00
committed by GitHub
parent 17f597695b
commit 3cc5ec7282
42 changed files with 360 additions and 66 deletions

View File

@@ -5,7 +5,7 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check-strings:
scripted-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
@@ -17,6 +17,8 @@ jobs:
run: tests/scripted/verify
- name: Run check-strings
run: tests/scripted/check-strings
- name: Run check-namespace
run: tests/scripted/check-namespace
shellcheck:
runs-on: ubuntu-latest
container: koalaman/shellcheck-alpine:v0.4.6

View File

@@ -143,7 +143,7 @@ private:
void *hostApiSpecificStreamInfo;
} PaStreamParameters;
#endif
#endif // PORTAUDIO_V19
PaStream * m_paStream;
PaStreamParameters m_outputParameters;

View File

@@ -102,6 +102,6 @@ private:
} // namespace lmms
#endif
#endif // LMMS_HAVE_PULSEAUDIO
#endif

View File

@@ -87,6 +87,6 @@ private:
} // namespace lmms
#endif /* LMMS_HAVE_SNDIO */
#endif // LMMS_HAVE_SNDIO
#endif /* _AUDIO_SNDIO_H */
#endif // _AUDIO_SNDIO_H

View File

@@ -50,7 +50,7 @@ public:
} ;
}
} // namespace gui
class DummyEffectControls : public EffectControls
{

View File

@@ -66,6 +66,6 @@ protected:
} ;
} // namesplace lmms
} // namespace lmms
#endif

View File

@@ -22,6 +22,8 @@
*
*/
#ifndef IO_HELPER_H
#define IO_HELPER_H
#include "lmmsconfig.h"
@@ -37,7 +39,7 @@
#ifdef LMMS_HAVE_UNISTD_H
#include <unistd.h>
#endif
#endif
#endif // LMMS_BUILD_WIN32
namespace lmms
{
@@ -87,4 +89,6 @@ int fileToDescriptor(FILE* f, bool closeFile = true)
}
} // namespace lmms
} // namespace lmms
#endif

View File

@@ -23,12 +23,12 @@
*
*/
#include <QWidget>
#include "lmms_export.h"
#ifndef LMMSPALETTE_H
#define LMMSPALETTE_H
#include <QWidget>
#include "lmms_export.h"
namespace lmms::gui
{

View File

@@ -73,6 +73,6 @@ private:
} // namespace lmms
#endif /* LMMS_HAVE_SNDIO */
#endif // LMMS_HAVE_SNDIO
#endif /* _MIDI_SNDIO_H */
#endif // _MIDI_SNDIO_H

View File

@@ -341,7 +341,7 @@ private:
std::atomic_int m_lockDepth;
} ;
#endif
#endif // SYNC_WITH_SHM_FIFO
@@ -530,7 +530,7 @@ public:
writeInt( len );
write( _s.c_str(), len );
}
#endif
#endif // SYNC_WITH_SHM_FIFO
#ifndef BUILD_REMOTE_PLUGIN_CLIENT
inline bool messagesLeft()
@@ -562,7 +562,7 @@ public:
{
return waitDepthCounter() > 0;
}
#endif
#endif // BUILD_REMOTE_PLUGIN_CLIENT
virtual bool processMessage( const message & _m ) = 0;
@@ -667,7 +667,7 @@ private:
pthread_mutex_t m_receiveMutex;
pthread_mutex_t m_sendMutex;
#endif
#endif // SYNC_WITH_SHM_FIFO
} ;

View File

@@ -173,7 +173,7 @@ private:
std::condition_variable m_cv;
std::thread m_thread;
};
#endif
#endif // LMMS_BUILD_WIN32
#ifdef SYNC_WITH_SHM_FIFO
RemotePluginClient::RemotePluginClient( const std::string& _shm_in, const std::string& _shm_out ) :

View File

@@ -33,7 +33,7 @@
#ifndef NDEBUG
#define NDEBUG
#endif
#endif
#endif // LMMS_DEBUG
#include <cassert>
#include <cstdio>

View File

@@ -65,7 +65,7 @@ inline QPixmap getIconPixmap( const QString& _name,
}
//QString getText( const char * _name );
}
} // namespace PLUGIN_NAME
#endif // PLUGIN_NAME

View File

@@ -118,7 +118,7 @@ static inline float absFraction( float _x )
}
#endif
#endif
#endif // __INTEL_COMPILER
@@ -153,7 +153,7 @@ static inline long double fastFmal( long double a, long double b, long double c
#endif
#else
return a * b + c;
#endif
#endif // FP_FAST_FMAL
}
//! @brief Takes advantage of fmaf() function if present in hardware
@@ -167,7 +167,7 @@ static inline float fastFmaf( float a, float b, float c )
#endif
#else
return a * b + c;
#endif
#endif // FP_FAST_FMAF
}
//! @brief Takes advantage of fma() function if present in hardware

View File

@@ -1,3 +1,6 @@
#ifndef VERSION_INFO_H
#define VERSION_INFO_H
#include "lmms_basics.h"
#ifdef __GNUC__
@@ -47,3 +50,5 @@ constexpr const char* LMMS_BUILDCONF_PLATFORM = "win32";
#ifdef LMMS_BUILD_HAIKU
constexpr const char* LMMS_BUILDCONF_PLATFORM = "Haiku";
#endif
#endif

View File

@@ -58,4 +58,4 @@ private:
} // namespace lmms
#endif // LMMS_HAVE_LV2
#endif

View File

@@ -57,7 +57,7 @@
#include <wine/exception.h>
#endif
#endif
#endif // LMMS_BUILD_LINUX
#ifndef NATIVE_LINUX_VST
#define USE_WS_PREFIX
@@ -883,7 +883,7 @@ void RemoteVstPlugin::initEditor()
pluginDispatch(effEditTop);
m_x11WindowVisible = true;
#endif
#endif // NATIVE_LINUX_VST
}
@@ -1090,16 +1090,16 @@ void RemoteVstPlugin::process( const sampleFrame * _in, sampleFrame * _out )
#ifdef OLD_VST_SDK
if( m_plugin->flags & effFlagsCanReplacing )
{
#endif
m_plugin->processReplacing( m_plugin, m_inputs, m_outputs,
bufferSize() );
#ifdef OLD_VST_SDK
}
else
{
m_plugin->process( m_plugin, m_inputs, m_outputs,
bufferSize() );
}
#else
m_plugin->processReplacing(m_plugin, m_inputs, m_outputs, bufferSize());
#endif
unlockShm();
@@ -1937,7 +1937,7 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode,
// TODO
// close window, platform specific handle in <ptr>
return 0;
#endif
#endif // OLD_VST_SDK
case audioMasterSizeWindow:
{
@@ -2334,7 +2334,7 @@ void RemoteVstPlugin::guiEventLoop()
}
}
}
#endif
#endif // NATIVE_LINUX_VST
#ifndef NATIVE_LINUX_VST
@@ -2385,7 +2385,7 @@ LRESULT CALLBACK RemoteVstPlugin::wndProc( HWND hwnd, UINT uMsg,
}
#endif
#endif // NATIVE_LINUX_VST
} // namespace lmms
@@ -2421,7 +2421,7 @@ int main( int _argc, char * * _argv )
sched_get_priority_min( SCHED_FIFO ) ) / 2;
sched_setscheduler( 0, SCHED_FIFO, &sparam );
#endif
#endif
#endif // LMMS_BUILD_LINUX
#ifdef LMMS_BUILD_WIN32
if( !SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS ) )

View File

@@ -111,7 +111,7 @@ private:
uchar* m_map;
};
}
} // namespace PE
namespace lmms
{

View File

@@ -363,7 +363,7 @@ namespace SimpleRandom {
return dist(generator);
}
};
}
} // namespace SimpleRandom
static freefunc0<float,SimpleRandom::float_random_with_engine,false> simple_rand;

View File

@@ -64,7 +64,7 @@ LocalZynAddSubFx::LocalZynAddSubFx() :
pthread_win32_process_attach_np();
pthread_win32_thread_attach_np();
#endif
#endif
#endif // LMMS_BUILD_WIN32
initConfig();

View File

@@ -278,7 +278,7 @@ int main( int _argc, char * * _argv )
pthread_win32_process_attach_np();
pthread_win32_thread_attach_np();
#endif
#endif
#endif // LMMS_BUILD_WIN32
#ifdef SYNC_WITH_SHM_FIFO
@@ -298,7 +298,7 @@ int main( int _argc, char * * _argv )
pthread_win32_thread_detach_np();
pthread_win32_process_detach_np();
#endif
#endif
#endif // LMMS_BUILD_WIN32
return 0;
}

View File

@@ -566,7 +566,7 @@ void ConfigManager::loadConfigFile(const QString & configFile)
}
#endif
}
#endif
#endif // LMMS_HAVE_STK
upgrade();

View File

@@ -37,7 +37,7 @@
#ifdef _MSC_VER
//not #if LMMS_BUILD_WIN32 because we have strncasecmp in mingw
#define strcasecmp _stricmp
#endif
#endif // _MSC_VER
namespace lmms
{

View File

@@ -672,7 +672,7 @@ f_cnt_t SampleBuffer::decodeSampleOGGVorbis(
return frames;
}
#endif
#endif // LMMS_HAVE_OGGVORBIS
@@ -1258,7 +1258,7 @@ void flacStreamEncoderMetadataCallback(
b->write((const char *) metadata, sizeof(*metadata));
}
#endif
#endif // LMMS_HAVE_FLAC_STREAM_ENCODER_H
@@ -1314,12 +1314,12 @@ QString & SampleBuffer::toBase64(QString & dst) const
base64::encode(baWriter.buffer().data(), baWriter.buffer().size(), dst);
#else /* LMMS_HAVE_FLAC_STREAM_ENCODER_H */
#else // LMMS_HAVE_FLAC_STREAM_ENCODER_H
base64::encode((const char *) m_data,
m_frames * sizeof(sampleFrame), dst);
#endif /* LMMS_HAVE_FLAC_STREAM_ENCODER_H */
#endif // LMMS_HAVE_FLAC_STREAM_ENCODER_H
return dst;
}
@@ -1461,7 +1461,7 @@ void flacStreamDecoderErrorCallback(
// what to do now??
}
#endif
#endif // LMMS_HAVE_FLAC_STREAM_DECODER_H
void SampleBuffer::loadFromBase64(const QString & data)
@@ -1517,7 +1517,7 @@ void SampleBuffer::loadFromBase64(const QString & data)
m_origData = MM_ALLOC<sampleFrame>( m_origFrames);
memcpy(m_origData, dst, dsize);
#endif
#endif // LMMS_HAVE_FLAC_STREAM_DECODER_H
delete[] dst;

View File

@@ -542,4 +542,4 @@ int AudioAlsa::setSWParams()
} // namespace lmms
#endif
#endif // LMMS_HAVE_ALSA

View File

@@ -134,4 +134,4 @@ void AudioFileMP3::tearDownEncoder()
} // namespace lmms
#endif
#endif // LMMS_HAVE_MP3LAME

View File

@@ -272,6 +272,6 @@ void AudioFileOgg::finishEncoding()
} // namespace lmms
#endif
#endif // LMMS_HAVE_OGGVORBIS

View File

@@ -339,7 +339,7 @@ void AudioJack::renamePort( AudioPort * _port )
#endif
}
}
#endif
#endif // AUDIO_PORT_SUPPORT
}
@@ -502,4 +502,4 @@ void AudioJack::setupWidget::saveSettings()
} // namespace lmms
#endif
#endif // LMMS_HAVE_JACK

View File

@@ -362,5 +362,5 @@ void AudioOss::setupWidget::saveSettings()
} // namespace lmms
#endif
#endif // LMMS_HAVE_OSS

View File

@@ -511,7 +511,7 @@ void AudioPortAudio::setupWidget::show()
} // namespace lmms
#endif
#endif // LMMS_HAVE_PORTAUDIO

View File

@@ -353,5 +353,5 @@ void AudioPulseAudio::setupWidget::saveSettings()
} // namespace lmms
#endif
#endif // LMMS_HAVE_PULSEAUDIO

View File

@@ -304,7 +304,7 @@ void AudioSdl::sdlAudioCallback( Uint8 * _buf, int _len )
m_convertedBufPos += min_len;
m_convertedBufPos %= m_convertedBufSize;
}
#endif
#endif // LMMS_HAVE_SDL2
}
#ifdef LMMS_HAVE_SDL2
@@ -349,5 +349,5 @@ void AudioSdl::setupWidget::saveSettings()
} // namespace lmms
#endif
#endif // LMMS_HAVE_SDL

View File

@@ -215,4 +215,4 @@ void AudioSndio::setupWidget::saveSettings()
} // namespace lmms
#endif /* LMMS_HAVE_SNDIO */
#endif // LMMS_HAVE_SNDIO

View File

@@ -521,4 +521,4 @@ void AudioSoundIo::setupWidget::saveSettings()
} // namespace lmms
#endif
#endif // LMMS_HAVE_SOUNDIO

View File

@@ -120,7 +120,7 @@ void consoleMessageHandler(QtMsgType type,
QByteArray localMsg = msg.toLocal8Bit();
fprintf(stderr, "%s\n", localMsg.constData());
}
#endif
#endif // LMMS_BUILD_WIN32
inline void loadTranslation( const QString & tname,
@@ -776,7 +776,7 @@ int main( int argc, char * * argv )
printf( "Notice: could not set realtime priority.\n" );
}
#endif
#endif
#endif // LMMS_HAVE_SCHED_H
#endif
#ifdef LMMS_BUILD_WIN32

View File

@@ -118,4 +118,4 @@ void MidiSndio::run()
} // namespace lmms
#endif /* LMMS_HAVE_SNDIO */
#endif // LMMS_HAVE_SNDIO

View File

@@ -120,4 +120,4 @@ void AudioAlsaSetupWidget::onCurrentIndexChanged(int index)
} // namespace lmms::gui
#endif
#endif // LMMS_HAVE_ALSA

View File

@@ -105,7 +105,7 @@ bool MainApplication::nativeEventFilter(const QByteArray& eventType,
}
return false;
}
#endif
#endif // LMMS_BUILD_WIN32
} // namespace lmms::gui

View File

@@ -624,4 +624,4 @@ void MixerView::updateFaders()
}
} // namesapce lmms::gui
} // namespace lmms::gui

View File

@@ -211,7 +211,7 @@ int PianoView::getKeyFromKeyEvent( QKeyEvent * _ke )
case 13: return 30; // =
case 27: return 31; // ]
}
#endif
#endif // LMMS_BUILD_WIN32
#if defined(LMMS_BUILD_LINUX) || defined(LMMS_BUILD_OPENBSD) || defined(LMMS_BUILD_FREEBSD)
switch( k )
{
@@ -292,7 +292,7 @@ int PianoView::getKeyFromKeyEvent( QKeyEvent * _ke )
case 29: return 27; // 0 = d'#
case 35: return 28; // P = e'
}
#endif
#endif // LMMS_BUILD_APPLE
return -100;
}

195
tests/scripted/check-namespace Executable file
View File

@@ -0,0 +1,195 @@
#!/usr/bin/python3
# This script checks the code for namespace related issues
# Note: This script is not perfect. It can not parse all LMMS files,
# and does not contain a complete C++ parser. If you encounter
# difficulties with this tests, it could be a fault of your
# changes, but it could also be a fault of this script.
import re
import subprocess
import sys
from pathlib import Path
from typing import NamedTuple
# types
class BlockType:
pass
IF_MACRO = BlockType()
HEADER_GUARD = BlockType()
CODE_BLOCK = BlockType()
EXTERN = BlockType()
class Expectation(NamedTuple):
type: BlockType
statement: str # expected end statement
name: str # expected name in comment
# global variables
errors = 0
# functions
def caption(my_str):
print(f'\n# {my_str}\n')
def error(where, match, my_str):
global errors
errors += 1
if match:
line = match.string[:match.start()].count('\n') + 1 # first line is 1
where = f'{where}:{line}'
print(f'Error: {where}: {my_str}')
if not Path('.gitmodules').is_file():
print('You need to call this script from the LMMS top directory')
exit(1)
result = subprocess.run(['git', 'ls-files', '*.[ch]', '*.[ch]pp', ':!tests/*'],
capture_output=True, text=True, check=True)
known_no_namespace_lmms = {
# main.cpp
'src/core/main.cpp',
# nothing to set under a namespace
'include/debug.h',
'include/versioninfo.h',
'plugins/CarlaBase/CarlaConfig/config.h',
'plugins/CarlaBase/DummyCarla.cpp',
# unclear why it has no namespace
'plugins/ZynAddSubFx/RemoteZynAddSubFx.cpp',
}
exclude_files = re.compile(
# not ours:
'include/(aeffectx|fenv|ladspa).h|'
'plugins/LadspaEffect/(calf|caps|cmt|swh|tap)/|'
'plugins/MidiExport/MidiFile.hpp|'
'plugins/ReverbSC/[a-z]|'
'plugins/Sf2Player/fluidsynthshims.h|'
'/portsmf/'
)
files = [Path(f) for f in result.stdout.splitlines() if not exclude_files.search(f)]
# Debug argument
if len(sys.argv) > 1:
files = [Path(arg) for arg in sys.argv[1:]]
statement_pattern = re.compile(
# Capture comments first to prevent them from matching any other regex
# Include next line if line ends with backslash
r'/[*](.|\n)*?[*]/|//(.*\\\n)*.*|'
# Macro with <30 lines and no other #if inside needs no end comment
# Match here to prevent from matching next regex
# With a (?!negative lookahead) we can allow all # except the ones followed by "if"
r'^ *# *(?P<short_macro>ifn?def)(?=(([^#\n]|#(?!if|endif))*\n){,30} *# *endif)|'
# Macro followed by name or comment
# With (?P<name>...) you can do a backreference to \name later
r'^ *# *(?P<named_macro>ifn?def|endif)(( *// *| +)(?P<macro_name>\w+))?|'
# Other macros where we don't want the argument
r'^ *# *(?P<macro>include|if|el(se|if))|'
# Namespace that contains no other braces needs no end comment
# With a (?=lookahead) we can let the "namespace" part be eaten by the parser
# but save the braces and their content for later so they can be matched again
r'^ *namespace *[\w:]*\s*(?={[^{}]*})|'
# Start of named namespace, extern "C" or just a opening brace
r'(^ *(namespace +(?P<namespace>[\w:]+)|(?P<extern>extern *"C"))\s*)?(?P<opening_brace>{)|'
# End of namespace including comment, or just a closing brace
r'(?P<closing_brace>})( *// *namespace +(?P<namespace_end>[\w:]+))?'
# In all the regexes above match both tab and space when a space is used
r''.replace(' ', r'[\t ]'),
# Make ^ match on every line, not just beginning of file
re.MULTILINE)
# Comments and whitespace followed by header guard
header_guard_pattern = re.compile(r'^(/[*](.|\n)*?[*]/|//.*|\s)*#\s*(ifndef|pragma\s+once)')
# Namespace lmms
namespace_pattern = re.compile(r'^\s*namespace\s+lmms', re.MULTILINE)
#
# the real code
#
caption('namespace checks')
for cur_file in files:
if cur_file.is_file():
cur_text = cur_file.read_text(errors='replace')
if str(cur_file) not in known_no_namespace_lmms:
namespace_pattern.search(cur_text) or error(cur_file, None, f'File has no namespace lmms')
header_guard = str(cur_file).endswith('.h')
expectations = [] # type: list[Expectation]
if header_guard:
if not header_guard_pattern.match(cur_text):
error(cur_file, None, 'First statement should be header guard')
header_guard = False
for m in statement_pattern.finditer(cur_text):
# Find the matched regex group
statement = m.group('opening_brace') or m.group('closing_brace')
if not statement:
statement = '#' + (m.group('macro') or m.group('named_macro') or m.group('short_macro') or '')
if not statement:
continue
# Start statements
if statement == '{':
etype = EXTERN if m.group('extern') else CODE_BLOCK
expectations.append(Expectation(etype, '}', m.group('namespace')))
elif statement.startswith('#if'):
etype = HEADER_GUARD if header_guard else IF_MACRO
expectations.append(Expectation(etype, '#endif', m.group('macro_name')))
header_guard = False
# End statements
elif statement == '#endif' or statement.startswith('#el') or statement == '}':
if not expectations:
error(cur_file, m, f'Unexpected {statement}')
break
# Don't pop the expectation for an #else tag, we are still waiting for the #endif
if statement.startswith('#el') and expectations[-1].statement == '#endif':
continue
exp = expectations.pop()
name = m.group('macro_name') or m.group('namespace_end') or ''
if statement != exp.statement:
error(cur_file, m, f'Expected {exp.statement} before {statement}')
break
# Require no end comment for header guard
elif exp.type is HEADER_GUARD and not name:
continue
elif exp.name and name != exp.name:
comment = 'namespace ' if exp.type is CODE_BLOCK else ''
error(cur_file, m, f'Missing comment // {comment}{exp.name}')
# Extra checks
elif statement == '#include':
if any(True for e in expectations if e.type is CODE_BLOCK):
error(cur_file, m, '#include inside a code block')
else:
# Leftover expected statements
for exp in reversed(expectations):
error(cur_file, None, f'Expected {exp.statement} before end of file')
caption('summary')
print(f'{str(errors)} errors.')
exit(1 if errors > 0 else 0)

View File

@@ -81,6 +81,7 @@ lmms_main_path = Path(__file__).resolve().parent.parent.parent
with tempfile.TemporaryDirectory() as tmpdir:
os.chdir(tmpdir)
check_strings = lmms_main_path / 'tests' / 'scripted' / 'check-strings'
check_namespace = lmms_main_path / 'tests' / 'scripted' / 'check-namespace'
# create dummy carla repo
Path('carla').mkdir()
@@ -158,5 +159,92 @@ with tempfile.TemporaryDirectory() as tmpdir:
test.expect('Error: debian/copyright: Glob/Path does not exist: NonExistent')
test.expect('1 errors')
with ScriptTest(check_namespace) as test:
# minimal working example
test.run(0) # exitcode 0 - no errors expected
test.expect('0 errors')
create_file('01_OddBraceWithinMacro.cpp', '''
#if HAS_EVEN_BRACES
namespace lmms {}
#endif
namespace lmms {
#if HAS_ODD_BRACE
}
#endif
''')
create_file('02_IncludeInCodeBlock.cpp', '''
#include <good>
extern "C" {
#include "alright.c"
}
namespace lmms {
#include <bad>
}
''')
create_file('03_MacroComments.h', '''
#ifndef HEADER_GUARD_NEEDS_NO_COMMENT
#define HEADER_GUARD_NEEDS_NO_COMMENT
#ifdef HAS_NESTED_NEEDS_COMMENT
#ifdef SHORT_NO_NESTED_NEEDS_NO_COMMENT
namespace lmms {}
#endif
#endif
#ifdef HAS_COMMENT
#ifdef SHORT_NO_NESTED_NEEDS_NO_COMMENT
#else
#endif
#endif // HAS_COMMENT
#endif
''')
create_file('04_NamespaceComments.cpp', '''
namespace lmms {
namespace ShortNamespace {
class WithDeclarationsOnly;
}
namespace LongNamespace {
class WithDefinition {
int x;
};
}
} // namespace lmms
''')
create_file('05_NoHeaderGuard.h', '''
#include <cstdio>
namespace lmms {}
''')
create_file('06_PragmaButNoLmms.h', '''
// should not cause header guard warning
#pragma once
namespace not_lmms {}
''')
create_file('07_MismatchingEndifName.h', '''
#ifndef ABC_H
namespace lmms {
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
}
#endif // XYZ_H
''')
create_file('08_MismatchingNamespaceEndName.h', '''
#ifndef ABC_H
namespace lmms {
{}
} // namespace smml
#endif // ABC_H
''')
test.run()
test.expect('8 errors')
test.expect('''
Error: 01_OddBraceWithinMacro.cpp:7: Expected #endif before }
Error: 02_IncludeInCodeBlock.cpp:7: #include inside a code block
Error: 03_MacroComments.h:8: Missing comment // HAS_NESTED_NEEDS_COMMENT
Error: 04_NamespaceComments.cpp:10: Missing comment // namespace LongNamespace
Error: 05_NoHeaderGuard.h: First statement should be header guard
Error: 06_PragmaButNoLmms.h: File has no namespace lmms
Error: 07_MismatchingEndifName.h:36: Missing comment // ABC_H
Error: 08_MismatchingNamespaceEndName.h:5: Missing comment // namespace lmms
''')
# if we made it until here without an exception, all tests have been passed
print("SUCCESS")