<commit_before>// Moon Phase Calendar for Arduino, using Pro Trinket 3V/12MHz

// Test support
#include "arduino.hpp"

// Arduino application
#include "../arduino/MoonPhaseCalendar/MoonPhaseCalendar.ino"

// Test program

#include "lest.hpp"
#include <iomanip>
#include <ostream>

using pause_ms = int;

template< typename T >
T setbit( T const x, int const pos, bool const on )
{
    return on ? x |  bit( pos )
              : x & ~bit( pos );
}

bool operator==( Date a, Date b )
{
    return a.year == b.year && a.month == b.month && a.day == b.day;
}

std::ostream & operator<< ( std::ostream & os, Date const & d )
{
    return os << "(" << d.year << "," << std::setw(2) << d.month << "," << std::setw(2) << d.day << ")" ;
}

#define CASE( name ) lest_CASE( specification(), name )

lest::tests & specification()
{
    static lest::tests tests;
    return tests;
}

// Test specification

namespace {

CASE( "Convenience: bit sets proper bit" )
{
    EXPECT( bit( 0 ) == 0x01 );
    EXPECT( bit( 1 ) == 0x02 );
    EXPECT( bit( 2 ) == 0x04 );
    EXPECT( bit( 3 ) == 0x08 );
    EXPECT( bit( 4 ) == 0x10 );
    EXPECT( bit( 5 ) == 0x20 );
    EXPECT( bit( 6 ) == 0x40 );
    EXPECT( bit( 7 ) == 0x80 );
}

CASE( "Convenience: bit tests true for set bits" )
{
    for ( int i = 0; i < 8; ++i )
        EXPECT( bitRead( bit(i), i ) );
}

CASE( "Convenience: bit tests false for unset bits" )
{
    for ( int i = 0; i < 8; ++i )
        for ( int k = i+1; k < 8; ++k )
            EXPECT_NOT( bitRead( bit(i), k ) );
}

CASE( "Convenience: setbit manipulates proper bit" )
{
    for ( int i = 0; i < 16 ; ++i )
    {
        EXPECT( setbit( 0x0000, i, true  ) == ( bit(i)          ) );
        EXPECT( setbit( 0xFFFF, i, false ) == ( bit(i) ^ 0xFFFF ) );
    }
}

CASE( "Electronics: Moon phase display sets pins properly" )
{
    static int pattern[] =
    {
        0b0000,
        0b0001,
        0b0011,
        0b0111,
        0b1111,
        0b1110,
        0b1100,
        0b1000,
    };
    static_assert( dimension_of(pattern) == phase_count, "expecting #pattern == pin_moon_count" );

    mock_setup();

    for ( int i = 0; i < 8; ++i )
    {
        display_moon_phase( i );

        EXPECT( pattern[i] == g_pin_value >> pin_moon_first );
    }
}

CASE( "Electronics: Date display: ... [.]" )
{
    mock_setup();
    EXPECT( !"Implement" );
}

CASE( "Electronics: Rotary encoder: ... [.]" )
{
    mock_setup();
    EXPECT( !"Implement" );
}

CASE( "Electronics: Button: ... [.]" )
{
    mock_setup();
    EXPECT( !"Implement" );
}

CASE( "Algorithm: A leap year if divisible by 400 [leap]" )
{
    EXPECT( is_leap_year( 1600 ) );
    EXPECT( is_leap_year( 2000 ) );
    EXPECT( is_leap_year( 2400 ) );
}

CASE( "Algorithm: A leap year if divisible by 4 but not by 100 [leap]" )
{
    EXPECT( is_leap_year( 1996 ) );
    EXPECT( is_leap_year( 2008 ) );
    EXPECT( is_leap_year( 2016 ) );
}

CASE( "Algorithm: Not a leap year if not divisible by 4 [leap]" )
{
    EXPECT_NOT( is_leap_year( 1998 ) );
    EXPECT_NOT( is_leap_year( 1999 ) );
    EXPECT_NOT( is_leap_year( 2010 ) );
}

CASE( "Algorithm: Not a leap year if divisible by 100 but not by 400 [leap]" )
{
    EXPECT_NOT( is_leap_year( 1800 ) );
    EXPECT_NOT( is_leap_year( 1900 ) );<commit_msg>Order tests as items appear in .ino file<commit_after>// Moon Phase Calendar for Arduino, using Pro Trinket 3V/12MHz

// Test support
#include "arduino.hpp"

// Arduino application
#include "../arduino/MoonPhaseCalendar/MoonPhaseCalendar.ino"

// Test program

#include "lest.hpp"
#include <iomanip>
#include <ostream>

using pause_ms = int;

template< typename T >
T setbit( T const x, int const pos, bool const on )
{
    return on ? x |  bit( pos )
              : x & ~bit( pos );
}

bool operator==( Date a, Date b )
{
    return a.year == b.year && a.month == b.month && a.day == b.day;
}

std::ostream & operator<< ( std::ostream & os, Date const & d )
{
    return os << "(" << d.year << "," << std::setw(2) << d.month << "," << std::setw(2) << d.day << ")" ;
}

#define CASE( name ) lest_CASE( specification(), name )

lest::tests & specification()
{
    static lest::tests tests;
    return tests;
}

// Test specification

namespace {

CASE( "Convenience: bit sets proper bit" )
{
    EXPECT( bit( 0 ) == 0x01 );
    EXPECT( bit( 1 ) == 0x02 );
    EXPECT( bit( 2 ) == 0x04 );
    EXPECT( bit( 3 ) == 0x08 );
    EXPECT( bit( 4 ) == 0x10 );
    EXPECT( bit( 5 ) == 0x20 );
    EXPECT( bit( 6 ) == 0x40 );
    EXPECT( bit( 7 ) == 0x80 );
}

CASE( "Convenience: bit tests true for set bits" )
{
    for ( int i = 0; i < 8; ++i )
        EXPECT( bitRead( bit(i), i ) );
}

CASE( "Convenience: bit tests false for unset bits" )
{
    for ( int i = 0; i < 8; ++i )
        for ( int k = i+1; k < 8; ++k )
            EXPECT_NOT( bitRead( bit(i), k ) );
}

CASE( "Convenience: setbit manipulates proper bit" )
{
    for ( int i = 0; i < 16 ; ++i )
    {
        EXPECT( setbit( 0x0000, i, true  ) == ( bit(i)          ) );
        EXPECT( setbit( 0xFFFF, i, false ) == ( bit(i) ^ 0xFFFF ) );
    }
}

CASE( "Electronics: Rotary encoder: ... [.]" )
{
    mock_setup();
    EXPECT( !"Implement" );
}

CASE( "Electronics: Button: ... [.]" )
{
    mock_setup();
    EXPECT( !"Implement" );
}

CASE( "Electronics: Date display: ... [.]" )
{
    mock_setup();
    EXPECT( !"Implement" );
}

CASE( "Electronics: Moon phase display sets pins properly" )
{
    static int pattern[] =
    {
        0b0000,
        0b0001,
        0b0011,
        0b0111,
        0b1111,
        0b1110,
        0b1100,
        0b1000,
    };
    static_assert( dimension_of(pattern) == phase_count, "expecting #pattern == pin_moon_count" );

    mock_setup();

    for ( int i = 0; i < 8; ++i )
    {
        display_moon_phase( i );

        EXPECT( pattern[i] == g_pin_value >> pin_moon_first );
    }
}

CASE( "Algorithm: A leap year if divisible by 400 [leap]" )
{
    EXPECT( is_leap_year( 1600 ) );
    EXPECT( is_leap_year( 2000 ) );
    EXPECT( is_leap_year( 2400 ) );
}

CASE( "Algorithm: A leap year if divisible by 4 but not by 100 [leap]" )
{
    EXPECT( is_leap_year( 1996 ) );
    EXPECT( is_leap_year( 2008 ) );
    EXPECT( is_leap_year( 2016 ) );
}

CASE( "Algorithm: Not a leap year if not divisible by 4 [leap]" )
{
    EXPECT_NOT( is_leap_year( 1998 ) );
    EXPECT_NOT( is_leap_year( 1999 ) );
    EXPECT_NOT( is_leap_year( 2010 ) );
}

CASE( "Algorithm: Not a leap year if divisible by 100 but not by 400 [leap]" )
{
    EXPECT_NOT( is_leap_year( 1800 ) );
    EXPECT_NOT( is_leap_year( 1900 ) );
{'fraction_non_alphanumeric': 0.16405178979436405, 'fraction_numerical': 0.04661081492764661, 'mean_word_length': 2.539622641509434, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1917226', 'n_tokens_mistral': 2719, 'n_tokens_neox': 2480, 'n_words': 699}