Skip to content

Commit 96db1c6

Browse files
committed
Ported legacy TestIncludesToIncludeFoldersDuplicateLibs* test
Also improved build options in test
1 parent 3755049 commit 96db1c6

File tree

17 files changed

+2003
-106
lines changed

17 files changed

+2003
-106
lines changed

internal/integrationtest/compile_4/compile_test.go

+78-15
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ func TestCompileOfProblematicSketches(t *testing.T) {
6363
_, _, err = cli.Run("lib", "install", "CapacitiveSensor@0.5")
6464
require.NoError(t, err)
6565

66+
// Install custom hardware required for tests
67+
customHwDir, err := paths.New("testdata", "user_hardware").Abs()
68+
require.NoError(t, err)
69+
require.NoError(t, customHwDir.CopyDirTo(cli.SketchbookDir().Join("hardware")))
70+
6671
integrationtest.CLISubtests{
6772
{"SketchWithInlineFunction", testBuilderSketchWithInlineFunction},
6873
{"SketchWithConst", testBuilderSketchWithConst},
@@ -98,6 +103,7 @@ func TestCompileOfProblematicSketches(t *testing.T) {
98103
{"USBHostExample", testBuilderUSBHostExample},
99104
{"SketchWithConflictingLibraries", testBuilderSketchWithConflictingLibraries},
100105
{"SketchLibraryProvidesAllIncludes", testBuilderSketchLibraryProvidesAllIncludes},
106+
{"UserHardware", testBuilderWithUserHardware},
101107
}.Run(t, env, cli)
102108
}
103109

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

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

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

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

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

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

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

575+
func testBuilderWithUserHardware(t *testing.T, env *integrationtest.Environment, cli *integrationtest.ArduinoCLI) {
576+
coreSPILib, err := cli.SketchbookDir().Join("hardware", "my_avr_platform", "avr", "libraries", "SPI").Abs()
577+
require.NoError(t, err)
578+
sketchPath := coreSPILib.Join("examples", "BarometricPressureSensor", "BarometricPressureSensor.ino")
579+
580+
t.Run("TestIncludesToIncludeFoldersDuplicateLibs", func(t *testing.T) {
581+
out, err := tryBuild(t, env, cli, "my_avr_platform:avr:custom_yun", &buildOptions{
582+
Sketch: sketchPath,
583+
NoTestLibraries: true,
584+
})
585+
require.NoError(t, err)
586+
587+
importedLibraries := out.BuilderResult.UsedLibraries
588+
require.Equal(t, 1, len(importedLibraries))
589+
require.Equal(t, "SPI", importedLibraries[0].Name)
590+
require.True(t, importedLibraries[0].SourceDir.EquivalentTo(coreSPILib))
591+
})
592+
593+
t.Run("TestIncludesToIncludeFoldersDuplicateLibsWithConflictingLibsOutsideOfPlatform", func(t *testing.T) {
594+
SPILib, err := paths.New("testdata", "libraries", "SPI").Abs()
595+
require.NoError(t, err)
596+
out, err := tryBuild(t, env, cli, "my_avr_platform:avr:custom_yun", &buildOptions{
597+
Sketch: sketchPath,
598+
})
599+
require.NoError(t, err)
600+
601+
importedLibraries := out.BuilderResult.UsedLibraries
602+
require.Equal(t, 1, len(importedLibraries))
603+
require.Equal(t, "SPI", importedLibraries[0].Name)
604+
require.True(t, importedLibraries[0].SourceDir.EquivalentTo(SPILib))
605+
})
606+
}
607+
569608
func tryBuildAvrLeonardo(t *testing.T, env *integrationtest.Environment, cli *integrationtest.ArduinoCLI) {
570609
_, err := tryBuild(t, env, cli, "arduino:avr:leonardo")
571610
require.NoError(t, err)
@@ -586,25 +625,49 @@ type builderLibrary struct {
586625
SourceDir *paths.Path `json:"source_dir"`
587626
}
588627

589-
func tryBuild(t *testing.T, env *integrationtest.Environment, cli *integrationtest.ArduinoCLI, fqbn string, options ...string) (*builderOutput, error) {
590-
subTestName := strings.Split(t.Name(), "/")[1]
591-
sketchPath, err := paths.New("testdata", subTestName).Abs()
592-
require.NoError(t, err)
593-
libsPath, err := paths.New("testdata", "libraries").Abs()
594-
require.NoError(t, err)
628+
type buildOptions struct {
629+
Sketch *paths.Path
630+
NoTestLibraries bool
631+
CustomLibPath *paths.Path
632+
NoClean bool
633+
AllWarnings bool
634+
Verbose bool
635+
}
636+
637+
func tryBuild(t *testing.T, env *integrationtest.Environment, cli *integrationtest.ArduinoCLI, fqbn string, optionsArg ...*buildOptions) (*builderOutput, error) {
638+
var options *buildOptions
639+
if len(optionsArg) == 0 {
640+
options = &buildOptions{}
641+
} else {
642+
require.Len(t, optionsArg, 1)
643+
options = optionsArg[0]
644+
}
645+
if options.Sketch == nil {
646+
subTestName := strings.Split(t.Name(), "/")[1]
647+
sketchPath, err := paths.New("testdata", subTestName).Abs()
648+
require.NoError(t, err)
649+
options.Sketch = sketchPath
650+
}
595651
args := []string{
596652
"compile",
597653
"-b", fqbn,
598-
"--libraries", libsPath.String(),
599654
"--format", "json",
600-
sketchPath.String()}
601-
if !slices.Contains(options, "no-clean") {
655+
options.Sketch.String()}
656+
if !options.NoTestLibraries {
657+
libsPath, err := paths.New("testdata", "libraries").Abs()
658+
require.NoError(t, err)
659+
args = append(args, "--libraries", libsPath.String())
660+
}
661+
if options.CustomLibPath != nil {
662+
args = append(args, "--library", options.CustomLibPath.String())
663+
}
664+
if !options.NoClean {
602665
args = append(args, "--clean")
603666
}
604-
if slices.Contains(options, "all-warnings") {
667+
if options.AllWarnings {
605668
args = append(args, "--warnings", "all")
606669
}
607-
if slices.Contains(options, "verbose") {
670+
if options.Verbose {
608671
args = append(args, "-v")
609672
}
610673
jsonOut, _, err := cli.Run(args...)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/*
2+
* Copyright (c) 2010 by Cristian Maglie <c.maglie@arduino.cc>
3+
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
4+
* Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
5+
* Copyright (c) 2014 by Andrew J. Kroll <xxxajk@gmail.com> (atomicity fixes)
6+
* SPI Master library for arduino.
7+
*
8+
* This file is free software; you can redistribute it and/or modify
9+
* it under the terms of either the GNU General Public License version 2
10+
* or the GNU Lesser General Public License version 2.1, both as
11+
* published by the Free Software Foundation.
12+
*/
13+
14+
#include "SPI.h"
15+
16+
SPIClass SPI;
17+
18+
uint8_t SPIClass::initialized = 0;
19+
uint8_t SPIClass::interruptMode = 0;
20+
uint8_t SPIClass::interruptMask = 0;
21+
uint8_t SPIClass::interruptSave = 0;
22+
#ifdef SPI_TRANSACTION_MISMATCH_LED
23+
uint8_t SPIClass::inTransactionFlag = 0;
24+
#endif
25+
26+
void SPIClass::begin()
27+
{
28+
uint8_t sreg = SREG;
29+
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
30+
if (!initialized) {
31+
// Set SS to high so a connected chip will be "deselected" by default
32+
uint8_t port = digitalPinToPort(SS);
33+
uint8_t bit = digitalPinToBitMask(SS);
34+
volatile uint8_t *reg = portModeRegister(port);
35+
36+
// if the SS pin is not already configured as an output
37+
// then set it high (to enable the internal pull-up resistor)
38+
if(!(*reg & bit)){
39+
digitalWrite(SS, HIGH);
40+
}
41+
42+
// When the SS pin is set as OUTPUT, it can be used as
43+
// a general purpose output port (it doesn't influence
44+
// SPI operations).
45+
pinMode(SS, OUTPUT);
46+
47+
// Warning: if the SS pin ever becomes a LOW INPUT then SPI
48+
// automatically switches to Slave, so the data direction of
49+
// the SS pin MUST be kept as OUTPUT.
50+
SPCR |= _BV(MSTR);
51+
SPCR |= _BV(SPE);
52+
53+
// Set direction register for SCK and MOSI pin.
54+
// MISO pin automatically overrides to INPUT.
55+
// By doing this AFTER enabling SPI, we avoid accidentally
56+
// clocking in a single bit since the lines go directly
57+
// from "input" to SPI control.
58+
// http://code.google.com/p/arduino/issues/detail?id=888
59+
pinMode(SCK, OUTPUT);
60+
pinMode(MOSI, OUTPUT);
61+
}
62+
initialized++; // reference count
63+
SREG = sreg;
64+
}
65+
66+
void SPIClass::end() {
67+
uint8_t sreg = SREG;
68+
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
69+
// Decrease the reference counter
70+
if (initialized)
71+
initialized--;
72+
// If there are no more references disable SPI
73+
if (!initialized) {
74+
SPCR &= ~_BV(SPE);
75+
interruptMode = 0;
76+
#ifdef SPI_TRANSACTION_MISMATCH_LED
77+
inTransactionFlag = 0;
78+
#endif
79+
}
80+
SREG = sreg;
81+
}
82+
83+
// mapping of interrupt numbers to bits within SPI_AVR_EIMSK
84+
#if defined(__AVR_ATmega32U4__)
85+
#define SPI_INT0_MASK (1<<INT0)
86+
#define SPI_INT1_MASK (1<<INT1)
87+
#define SPI_INT2_MASK (1<<INT2)
88+
#define SPI_INT3_MASK (1<<INT3)
89+
#define SPI_INT4_MASK (1<<INT6)
90+
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
91+
#define SPI_INT0_MASK (1<<INT0)
92+
#define SPI_INT1_MASK (1<<INT1)
93+
#define SPI_INT2_MASK (1<<INT2)
94+
#define SPI_INT3_MASK (1<<INT3)
95+
#define SPI_INT4_MASK (1<<INT4)
96+
#define SPI_INT5_MASK (1<<INT5)
97+
#define SPI_INT6_MASK (1<<INT6)
98+
#define SPI_INT7_MASK (1<<INT7)
99+
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
100+
#define SPI_INT0_MASK (1<<INT4)
101+
#define SPI_INT1_MASK (1<<INT5)
102+
#define SPI_INT2_MASK (1<<INT0)
103+
#define SPI_INT3_MASK (1<<INT1)
104+
#define SPI_INT4_MASK (1<<INT2)
105+
#define SPI_INT5_MASK (1<<INT3)
106+
#define SPI_INT6_MASK (1<<INT6)
107+
#define SPI_INT7_MASK (1<<INT7)
108+
#else
109+
#ifdef INT0
110+
#define SPI_INT0_MASK (1<<INT0)
111+
#endif
112+
#ifdef INT1
113+
#define SPI_INT1_MASK (1<<INT1)
114+
#endif
115+
#ifdef INT2
116+
#define SPI_INT2_MASK (1<<INT2)
117+
#endif
118+
#endif
119+
120+
void SPIClass::usingInterrupt(uint8_t interruptNumber)
121+
{
122+
uint8_t mask = 0;
123+
uint8_t sreg = SREG;
124+
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
125+
switch (interruptNumber) {
126+
#ifdef SPI_INT0_MASK
127+
case 0: mask = SPI_INT0_MASK; break;
128+
#endif
129+
#ifdef SPI_INT1_MASK
130+
case 1: mask = SPI_INT1_MASK; break;
131+
#endif
132+
#ifdef SPI_INT2_MASK
133+
case 2: mask = SPI_INT2_MASK; break;
134+
#endif
135+
#ifdef SPI_INT3_MASK
136+
case 3: mask = SPI_INT3_MASK; break;
137+
#endif
138+
#ifdef SPI_INT4_MASK
139+
case 4: mask = SPI_INT4_MASK; break;
140+
#endif
141+
#ifdef SPI_INT5_MASK
142+
case 5: mask = SPI_INT5_MASK; break;
143+
#endif
144+
#ifdef SPI_INT6_MASK
145+
case 6: mask = SPI_INT6_MASK; break;
146+
#endif
147+
#ifdef SPI_INT7_MASK
148+
case 7: mask = SPI_INT7_MASK; break;
149+
#endif
150+
default:
151+
interruptMode = 2;
152+
break;
153+
}
154+
interruptMask |= mask;
155+
if (!interruptMode)
156+
interruptMode = 1;
157+
SREG = sreg;
158+
}
159+
160+
void SPIClass::notUsingInterrupt(uint8_t interruptNumber)
161+
{
162+
// Once in mode 2 we can't go back to 0 without a proper reference count
163+
if (interruptMode == 2)
164+
return;
165+
uint8_t mask = 0;
166+
uint8_t sreg = SREG;
167+
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
168+
switch (interruptNumber) {
169+
#ifdef SPI_INT0_MASK
170+
case 0: mask = SPI_INT0_MASK; break;
171+
#endif
172+
#ifdef SPI_INT1_MASK
173+
case 1: mask = SPI_INT1_MASK; break;
174+
#endif
175+
#ifdef SPI_INT2_MASK
176+
case 2: mask = SPI_INT2_MASK; break;
177+
#endif
178+
#ifdef SPI_INT3_MASK
179+
case 3: mask = SPI_INT3_MASK; break;
180+
#endif
181+
#ifdef SPI_INT4_MASK
182+
case 4: mask = SPI_INT4_MASK; break;
183+
#endif
184+
#ifdef SPI_INT5_MASK
185+
case 5: mask = SPI_INT5_MASK; break;
186+
#endif
187+
#ifdef SPI_INT6_MASK
188+
case 6: mask = SPI_INT6_MASK; break;
189+
#endif
190+
#ifdef SPI_INT7_MASK
191+
case 7: mask = SPI_INT7_MASK; break;
192+
#endif
193+
default:
194+
break;
195+
// this case can't be reached
196+
}
197+
interruptMask &= ~mask;
198+
if (!interruptMask)
199+
interruptMode = 0;
200+
SREG = sreg;
201+
}

0 commit comments

Comments
 (0)