Skip to content

Commit

Permalink
Ported legacy TestIncludesToIncludeFoldersDuplicateLibs* test
Browse files Browse the repository at this point in the history
Also improved build options in test
  • Loading branch information
cmaglie committed Sep 5, 2023
1 parent f029797 commit 5eb2a98
Show file tree
Hide file tree
Showing 17 changed files with 2,003 additions and 106 deletions.
93 changes: 78 additions & 15 deletions internal/integrationtest/compile_4/compile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ func TestCompileOfProblematicSketches(t *testing.T) {
_, _, err = cli.Run("lib", "install", "[email protected]")
require.NoError(t, err)

// Install custom hardware required for tests
customHwDir, err := paths.New("testdata", "user_hardware").Abs()
require.NoError(t, err)
require.NoError(t, customHwDir.CopyDirTo(cli.SketchbookDir().Join("hardware")))

integrationtest.CLISubtests{
{"SketchWithInlineFunction", testBuilderSketchWithInlineFunction},
{"SketchWithConst", testBuilderSketchWithConst},
Expand Down Expand Up @@ -98,6 +103,7 @@ func TestCompileOfProblematicSketches(t *testing.T) {
{"USBHostExample", testBuilderUSBHostExample},
{"SketchWithConflictingLibraries", testBuilderSketchWithConflictingLibraries},
{"SketchLibraryProvidesAllIncludes", testBuilderSketchLibraryProvidesAllIncludes},
{"UserHardware", testBuilderWithUserHardware},
}.Run(t, env, cli)
}

Expand Down Expand Up @@ -328,7 +334,7 @@ func testBuilderBridgeExample(t *testing.T, env *integrationtest.Environment, cl
require.Equal(t, "Bridge", libs[0].Name)

// Build again...
out2, err2 := tryBuild(t, env, cli, "arduino:avr:leonardo", "no-clean")
out2, err2 := tryBuild(t, env, cli, "arduino:avr:leonardo", &buildOptions{NoClean: true})
require.NoError(t, err2)
buildPath2 := out2.BuilderResult.BuildPath
require.True(t, buildPath2.Join("core", "HardwareSerial.cpp.o").Exist())
Expand All @@ -340,7 +346,7 @@ func testBuilderBridgeExample(t *testing.T, env *integrationtest.Environment, cl

t.Run("BuildForSAM", func(t *testing.T) {
// Build again for SAM...
out, err := tryBuild(t, env, cli, "arduino:sam:arduino_due_x_dbg", "all-warnings")
out, err := tryBuild(t, env, cli, "arduino:sam:arduino_due_x_dbg", &buildOptions{AllWarnings: true})
require.NoError(t, err)

buildPath := out.BuilderResult.BuildPath
Expand All @@ -363,7 +369,7 @@ func testBuilderBridgeExample(t *testing.T, env *integrationtest.Environment, cl

t.Run("BuildForRedBearAVR", func(t *testing.T) {
// Build again for RedBearLab...
out, err := tryBuild(t, env, cli, "RedBear:avr:blend", "verbose")
out, err := tryBuild(t, env, cli, "RedBear:avr:blend", &buildOptions{Verbose: true})
require.NoError(t, err)
buildPath := out.BuilderResult.BuildPath
require.True(t, buildPath.Join("core", "HardwareSerial.cpp.o").Exist())
Expand All @@ -382,7 +388,7 @@ func testBuilderBridgeExample(t *testing.T, env *integrationtest.Environment, cl
require.NoError(t, buildPath.Join("libraries", "SPI").MkdirAll())

// Build again...
_, err = tryBuild(t, env, cli, "arduino:avr:leonardo", "no-clean")
_, err = tryBuild(t, env, cli, "arduino:avr:leonardo", &buildOptions{NoClean: true})
require.NoError(t, err)

require.False(t, buildPath.Join("libraries", "SPI").Exist())
Expand Down Expand Up @@ -566,6 +572,39 @@ func testBuilderSketchLibraryProvidesAllIncludes(t *testing.T, env *integrationt
})
}

func testBuilderWithUserHardware(t *testing.T, env *integrationtest.Environment, cli *integrationtest.ArduinoCLI) {
coreSPILib, err := cli.SketchbookDir().Join("hardware", "my_avr_platform", "avr", "libraries", "SPI").Abs()
require.NoError(t, err)
sketchPath := coreSPILib.Join("examples", "BarometricPressureSensor", "BarometricPressureSensor.ino")

t.Run("TestIncludesToIncludeFoldersDuplicateLibs", func(t *testing.T) {
out, err := tryBuild(t, env, cli, "my_avr_platform:avr:custom_yun", &buildOptions{
Sketch: sketchPath,
NoTestLibraries: true,
})
require.NoError(t, err)

importedLibraries := out.BuilderResult.UsedLibraries
require.Equal(t, 1, len(importedLibraries))
require.Equal(t, "SPI", importedLibraries[0].Name)
require.True(t, importedLibraries[0].SourceDir.EquivalentTo(coreSPILib))
})

t.Run("TestIncludesToIncludeFoldersDuplicateLibsWithConflictingLibsOutsideOfPlatform", func(t *testing.T) {
SPILib, err := paths.New("testdata", "libraries", "SPI").Abs()
require.NoError(t, err)
out, err := tryBuild(t, env, cli, "my_avr_platform:avr:custom_yun", &buildOptions{
Sketch: sketchPath,
})
require.NoError(t, err)

importedLibraries := out.BuilderResult.UsedLibraries
require.Equal(t, 1, len(importedLibraries))
require.Equal(t, "SPI", importedLibraries[0].Name)
require.True(t, importedLibraries[0].SourceDir.EquivalentTo(SPILib))
})
}

func tryBuildAvrLeonardo(t *testing.T, env *integrationtest.Environment, cli *integrationtest.ArduinoCLI) {
_, err := tryBuild(t, env, cli, "arduino:avr:leonardo")
require.NoError(t, err)
Expand All @@ -586,25 +625,49 @@ type builderLibrary struct {
SourceDir *paths.Path `json:"source_dir"`
}

func tryBuild(t *testing.T, env *integrationtest.Environment, cli *integrationtest.ArduinoCLI, fqbn string, options ...string) (*builderOutput, error) {
subTestName := strings.Split(t.Name(), "/")[1]
sketchPath, err := paths.New("testdata", subTestName).Abs()
require.NoError(t, err)
libsPath, err := paths.New("testdata", "libraries").Abs()
require.NoError(t, err)
type buildOptions struct {
Sketch *paths.Path
NoTestLibraries bool
CustomLibPath *paths.Path
NoClean bool
AllWarnings bool
Verbose bool
}

func tryBuild(t *testing.T, env *integrationtest.Environment, cli *integrationtest.ArduinoCLI, fqbn string, optionsArg ...*buildOptions) (*builderOutput, error) {
var options *buildOptions
if len(optionsArg) == 0 {
options = &buildOptions{}
} else {
require.Len(t, optionsArg, 1)
options = optionsArg[0]
}
if options.Sketch == nil {
subTestName := strings.Split(t.Name(), "/")[1]
sketchPath, err := paths.New("testdata", subTestName).Abs()
require.NoError(t, err)
options.Sketch = sketchPath
}
args := []string{
"compile",
"-b", fqbn,
"--libraries", libsPath.String(),
"--format", "json",
sketchPath.String()}
if !slices.Contains(options, "no-clean") {
options.Sketch.String()}
if !options.NoTestLibraries {
libsPath, err := paths.New("testdata", "libraries").Abs()
require.NoError(t, err)
args = append(args, "--libraries", libsPath.String())
}
if options.CustomLibPath != nil {
args = append(args, "--library", options.CustomLibPath.String())
}
if !options.NoClean {
args = append(args, "--clean")
}
if slices.Contains(options, "all-warnings") {
if options.AllWarnings {
args = append(args, "--warnings", "all")
}
if slices.Contains(options, "verbose") {
if options.Verbose {
args = append(args, "-v")
}
jsonOut, _, err := cli.Run(args...)
Expand Down
201 changes: 201 additions & 0 deletions internal/integrationtest/compile_4/testdata/libraries/SPI/SPI.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
* Copyright (c) 2010 by Cristian Maglie <[email protected]>
* Copyright (c) 2014 by Paul Stoffregen <[email protected]> (Transaction API)
* Copyright (c) 2014 by Matthijs Kooijman <[email protected]> (SPISettings AVR)
* Copyright (c) 2014 by Andrew J. Kroll <[email protected]> (atomicity fixes)
* SPI Master library for arduino.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/

#include "SPI.h"

SPIClass SPI;

uint8_t SPIClass::initialized = 0;
uint8_t SPIClass::interruptMode = 0;
uint8_t SPIClass::interruptMask = 0;
uint8_t SPIClass::interruptSave = 0;
#ifdef SPI_TRANSACTION_MISMATCH_LED
uint8_t SPIClass::inTransactionFlag = 0;
#endif

void SPIClass::begin()
{
uint8_t sreg = SREG;
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
if (!initialized) {
// Set SS to high so a connected chip will be "deselected" by default
uint8_t port = digitalPinToPort(SS);
uint8_t bit = digitalPinToBitMask(SS);
volatile uint8_t *reg = portModeRegister(port);

// if the SS pin is not already configured as an output
// then set it high (to enable the internal pull-up resistor)
if(!(*reg & bit)){
digitalWrite(SS, HIGH);
}

// When the SS pin is set as OUTPUT, it can be used as
// a general purpose output port (it doesn't influence
// SPI operations).
pinMode(SS, OUTPUT);

// Warning: if the SS pin ever becomes a LOW INPUT then SPI
// automatically switches to Slave, so the data direction of
// the SS pin MUST be kept as OUTPUT.
SPCR |= _BV(MSTR);
SPCR |= _BV(SPE);

// Set direction register for SCK and MOSI pin.
// MISO pin automatically overrides to INPUT.
// By doing this AFTER enabling SPI, we avoid accidentally
// clocking in a single bit since the lines go directly
// from "input" to SPI control.
// http://code.google.com/p/arduino/issues/detail?id=888
pinMode(SCK, OUTPUT);
pinMode(MOSI, OUTPUT);
}
initialized++; // reference count
SREG = sreg;
}

void SPIClass::end() {
uint8_t sreg = SREG;
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
// Decrease the reference counter
if (initialized)
initialized--;
// If there are no more references disable SPI
if (!initialized) {
SPCR &= ~_BV(SPE);
interruptMode = 0;
#ifdef SPI_TRANSACTION_MISMATCH_LED
inTransactionFlag = 0;
#endif
}
SREG = sreg;
}

// mapping of interrupt numbers to bits within SPI_AVR_EIMSK
#if defined(__AVR_ATmega32U4__)
#define SPI_INT0_MASK (1<<INT0)
#define SPI_INT1_MASK (1<<INT1)
#define SPI_INT2_MASK (1<<INT2)
#define SPI_INT3_MASK (1<<INT3)
#define SPI_INT4_MASK (1<<INT6)
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
#define SPI_INT0_MASK (1<<INT0)
#define SPI_INT1_MASK (1<<INT1)
#define SPI_INT2_MASK (1<<INT2)
#define SPI_INT3_MASK (1<<INT3)
#define SPI_INT4_MASK (1<<INT4)
#define SPI_INT5_MASK (1<<INT5)
#define SPI_INT6_MASK (1<<INT6)
#define SPI_INT7_MASK (1<<INT7)
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
#define SPI_INT0_MASK (1<<INT4)
#define SPI_INT1_MASK (1<<INT5)
#define SPI_INT2_MASK (1<<INT0)
#define SPI_INT3_MASK (1<<INT1)
#define SPI_INT4_MASK (1<<INT2)
#define SPI_INT5_MASK (1<<INT3)
#define SPI_INT6_MASK (1<<INT6)
#define SPI_INT7_MASK (1<<INT7)
#else
#ifdef INT0
#define SPI_INT0_MASK (1<<INT0)
#endif
#ifdef INT1
#define SPI_INT1_MASK (1<<INT1)
#endif
#ifdef INT2
#define SPI_INT2_MASK (1<<INT2)
#endif
#endif

void SPIClass::usingInterrupt(uint8_t interruptNumber)
{
uint8_t mask = 0;
uint8_t sreg = SREG;
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
switch (interruptNumber) {
#ifdef SPI_INT0_MASK
case 0: mask = SPI_INT0_MASK; break;
#endif
#ifdef SPI_INT1_MASK
case 1: mask = SPI_INT1_MASK; break;
#endif
#ifdef SPI_INT2_MASK
case 2: mask = SPI_INT2_MASK; break;
#endif
#ifdef SPI_INT3_MASK
case 3: mask = SPI_INT3_MASK; break;
#endif
#ifdef SPI_INT4_MASK
case 4: mask = SPI_INT4_MASK; break;
#endif
#ifdef SPI_INT5_MASK
case 5: mask = SPI_INT5_MASK; break;
#endif
#ifdef SPI_INT6_MASK
case 6: mask = SPI_INT6_MASK; break;
#endif
#ifdef SPI_INT7_MASK
case 7: mask = SPI_INT7_MASK; break;
#endif
default:
interruptMode = 2;
break;
}
interruptMask |= mask;
if (!interruptMode)
interruptMode = 1;
SREG = sreg;
}

void SPIClass::notUsingInterrupt(uint8_t interruptNumber)
{
// Once in mode 2 we can't go back to 0 without a proper reference count
if (interruptMode == 2)
return;
uint8_t mask = 0;
uint8_t sreg = SREG;
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
switch (interruptNumber) {
#ifdef SPI_INT0_MASK
case 0: mask = SPI_INT0_MASK; break;
#endif
#ifdef SPI_INT1_MASK
case 1: mask = SPI_INT1_MASK; break;
#endif
#ifdef SPI_INT2_MASK
case 2: mask = SPI_INT2_MASK; break;
#endif
#ifdef SPI_INT3_MASK
case 3: mask = SPI_INT3_MASK; break;
#endif
#ifdef SPI_INT4_MASK
case 4: mask = SPI_INT4_MASK; break;
#endif
#ifdef SPI_INT5_MASK
case 5: mask = SPI_INT5_MASK; break;
#endif
#ifdef SPI_INT6_MASK
case 6: mask = SPI_INT6_MASK; break;
#endif
#ifdef SPI_INT7_MASK
case 7: mask = SPI_INT7_MASK; break;
#endif
default:
break;
// this case can't be reached
}
interruptMask &= ~mask;
if (!interruptMask)
interruptMode = 0;
SREG = sreg;
}
Loading

0 comments on commit 5eb2a98

Please sign in to comment.