mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
The SDFS implementation didn't include plumbing to support user-supplied timestamp generators (for file create/write times) because the SDFat library doesn't support a callback parameter. Work around it by using a single, global (inside sdfs namespace) that the static timestamp callback member can see and use. Add a test of the feature in CI. Fixes #7682
197 lines
5.3 KiB
C++
197 lines
5.3 KiB
C++
/*
|
|
test_fs.cpp - host side file system tests
|
|
Copyright © 2016 Ivan Grokhotkov
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
*/
|
|
|
|
#include <catch.hpp>
|
|
#include <map>
|
|
#include <FS.h>
|
|
#include "../common/spiffs_mock.h"
|
|
#include "../common/littlefs_mock.h"
|
|
#include "../common/sdfs_mock.h"
|
|
#include <spiffs/spiffs.h>
|
|
#include <LittleFS.h>
|
|
#include "../../../libraries/SDFS/src/SDFS.h"
|
|
#include "../../../libraries/SD/src/SD.h"
|
|
|
|
|
|
namespace spiffs_test {
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
|
|
#define FSTYPE SPIFFS
|
|
#define TESTPRE "SPIFFS - "
|
|
#define TESTPAT "[fs]"
|
|
#define TOOLONGFILENAME "/2345678901234567890123456789012"
|
|
#define FS_MOCK_DECLARE SPIFFS_MOCK_DECLARE
|
|
#define FS_MOCK_RESET SPIFFS_MOCK_RESET
|
|
#undef FS_HAS_DIRS
|
|
#include "test_fs.inc"
|
|
#undef FSTYPE
|
|
#undef TESTPRE
|
|
#undef TESTPAT
|
|
#undef TOOLONGFILENAME
|
|
#undef FS_MOCK_DECLARE
|
|
#undef FS_MOCK_RESET
|
|
|
|
TEST_CASE("SPIFFS checks the config object passed in", "[fs]")
|
|
{
|
|
SPIFFS_MOCK_DECLARE(64, 8, 512, "");
|
|
FSConfig f;
|
|
SPIFFSConfig s;
|
|
SDFSConfig d;
|
|
LittleFSConfig l;
|
|
|
|
REQUIRE_FALSE(SPIFFS.setConfig(f));
|
|
REQUIRE(SPIFFS.setConfig(s));
|
|
REQUIRE_FALSE(SPIFFS.setConfig(d));
|
|
REQUIRE_FALSE(LittleFS.setConfig(l));
|
|
}
|
|
#pragma GCC diagnostic pop
|
|
|
|
};
|
|
|
|
|
|
namespace littlefs_test {
|
|
#define FSTYPE LittleFS
|
|
#define TESTPRE "LittleFS - "
|
|
#define TESTPAT "[lfs]"
|
|
// LittleFS routines strip leading slashes before doing anything, so up to 31 char names are allowable
|
|
#define TOOLONGFILENAME "/12345678901234567890123456789012"
|
|
#define FS_MOCK_DECLARE LITTLEFS_MOCK_DECLARE
|
|
#define FS_MOCK_RESET LITTLEFS_MOCK_RESET
|
|
#define FS_HAS_DIRS
|
|
#include "test_fs.inc"
|
|
#undef FSTYPE
|
|
#undef TESTPRE
|
|
#undef TESTPAT
|
|
#undef TOOLONGFILENAME
|
|
#undef FS_MOCK_DECLARE
|
|
#undef FS_MOCK_RESET
|
|
|
|
TEST_CASE("LittleFS checks the config object passed in", "[fs]")
|
|
{
|
|
LITTLEFS_MOCK_DECLARE(64, 8, 512, "");
|
|
FSConfig f;
|
|
SPIFFSConfig s;
|
|
SDFSConfig d;
|
|
LittleFSConfig l;
|
|
|
|
REQUIRE_FALSE(LittleFS.setConfig(f));
|
|
REQUIRE_FALSE(LittleFS.setConfig(s));
|
|
REQUIRE_FALSE(LittleFS.setConfig(d));
|
|
REQUIRE(LittleFS.setConfig(l));
|
|
}
|
|
|
|
};
|
|
|
|
namespace sdfs_test {
|
|
#define FSTYPE SDFS
|
|
#define TESTPRE "SDFS - "
|
|
#define TESTPAT "[sdfs]"
|
|
// SDFS supports long paths (MAXPATH)
|
|
#define TOOLONGFILENAME "/" \
|
|
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" \
|
|
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" \
|
|
"12345678901234567890123456789012345678901234567890123456"
|
|
#define FS_MOCK_DECLARE SDFS_MOCK_DECLARE
|
|
#define FS_MOCK_RESET SDFS_MOCK_RESET
|
|
#define FS_HAS_DIRS
|
|
#include "test_fs.inc"
|
|
#undef FSTYPE
|
|
#undef TESTPRE
|
|
#undef TESTPAT
|
|
#undef TOOLONGFILENAME
|
|
#undef FS_MOCK_DECLARE
|
|
#undef FS_MOCK_RESET
|
|
|
|
TEST_CASE("SDFS checks the config object passed in", "[fs]")
|
|
{
|
|
SDFS_MOCK_DECLARE(64, 8, 512, "");
|
|
FSConfig f;
|
|
SPIFFSConfig s;
|
|
SDFSConfig d;
|
|
LittleFSConfig l;
|
|
|
|
REQUIRE_FALSE(SDFS.setConfig(f));
|
|
REQUIRE_FALSE(SDFS.setConfig(s));
|
|
REQUIRE(SDFS.setConfig(d));
|
|
REQUIRE_FALSE(SDFS.setConfig(l));
|
|
}
|
|
|
|
// Also a SD specific test to check that FILE_OPEN is really an append operation:
|
|
|
|
TEST_CASE("SD.h FILE_WRITE macro is append", "[fs]")
|
|
{
|
|
SDFS_MOCK_DECLARE(64, 8, 512, "");
|
|
REQUIRE(SDFS.begin());
|
|
REQUIRE(SD.begin(4));
|
|
|
|
File f = SD.open("/file.txt", FILE_WRITE);
|
|
f.write('a');
|
|
f.write(65);
|
|
f.write("bbcc");
|
|
f.write("theend", 6);
|
|
char block[3]={'x','y','z'};
|
|
f.write(block, 3);
|
|
uint32_t bigone = 0x40404040;
|
|
f.write((const uint8_t*)&bigone, 4);
|
|
f.close();
|
|
REQUIRE(readFile("/file.txt") == "aAbbcctheendxyz@@@@");
|
|
f = SD.open("/file.txt", FILE_WRITE);
|
|
f.write("append", 6);
|
|
f.close();
|
|
REQUIRE(readFile("/file.txt") == "aAbbcctheendxyz@@@@append");
|
|
File g = SD.open("/file2.txt", FILE_WRITE);
|
|
g.write(0);
|
|
g.close();
|
|
g = SD.open("/file2.txt", FILE_READ);
|
|
uint8_t u = 0x66;
|
|
g.read(&u, 1);
|
|
g.close();
|
|
REQUIRE(u == 0);
|
|
}
|
|
|
|
// SDFS timestamp setter (#7682)
|
|
static time_t _my_time(void)
|
|
{
|
|
struct tm t;
|
|
bzero(&t, sizeof(t));
|
|
t.tm_year = 120;
|
|
t.tm_mon = 9;
|
|
t.tm_mday = 22;
|
|
t.tm_hour = 12;
|
|
t.tm_min = 13;
|
|
t.tm_sec = 14;
|
|
return mktime(&t);
|
|
}
|
|
|
|
TEST_CASE("SDFS timeCallback")
|
|
{
|
|
SDFS_MOCK_DECLARE(64, 8, 512, "");
|
|
REQUIRE(SDFS.begin());
|
|
REQUIRE(SD.begin(4));
|
|
|
|
SDFS.setTimeCallback(_my_time);
|
|
File f = SD.open("/file.txt", "w");
|
|
f.write("Had we but world enough, and time,");
|
|
f.close();
|
|
time_t expected = _my_time();
|
|
f = SD.open("/file.txt", "r");
|
|
REQUIRE(abs(f.getCreationTime() - expected) < 60); // FAT has less precision in timestamp than time_t
|
|
REQUIRE(abs(f.getLastWrite() - expected) < 60); // FAT has less precision in timestamp than time_t
|
|
f.close();
|
|
}
|
|
|
|
};
|