Skip to content
This repository has been archived by the owner on Mar 4, 2024. It is now read-only.

Commit

Permalink
Initial CI for MacOS
Browse files Browse the repository at this point in the history
  • Loading branch information
rabits committed May 11, 2021
1 parent 218928d commit 4bfa80a
Show file tree
Hide file tree
Showing 15 changed files with 229 additions and 63 deletions.
26 changes: 22 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ jobs:
dist: focal
arch: amd64

- os: osx
osx_image: xcode12.2

- if: type != pull_request
compiler: clang
dist: bionic
Expand All @@ -60,19 +63,34 @@ jobs:
before_script:
- git clone --depth 1 https://github.com/edlund/amalgamate.git
- export PATH=$PATH:$PWD/amalgamate
- | # Build libuv dependency on MacOS
if [ $TRAVIS_OS_NAME = 'osx' ]; then
git clone --depth 1 https://github.com/libuv/libuv.git
cd libuv
git checkout v1.41.0
sh autogen.sh
./configure
make -j8
fi
script:
- cd "$TRAVIS_BUILD_DIR"
- autoreconf -i
- | # Use built libuv on MacOS
if [ $TRAVIS_OS_NAME = 'osx' ]; then
export UV_CFLAGS="-I$(pwd)/libuv/include"
export UV_LIBS="-L$(pwd)/libuv/.libs -luv"
fi
- |
if [ $TRAVIS_CPU_ARCH = "s390x" ] || [ $TRAVIS_CPU_ARCH = "arm64" ]; then
./configure --enable-example --enable-debug --enable-code-coverage
if [ "$TRAVIS_CPU_ARCH" = "s390x" -o "$TRAVIS_CPU_ARCH" = "arm64" ]; then
./configure --enable-example --enable-debug $([ $TRAVIS_OS_NAME = 'osx' ] || echo '--enable-code-coverage')
else
./configure --enable-example --enable-debug --enable-code-coverage --enable-sanitize
fi
- amalgamate.py --config=amalgamation.json --source=$(pwd)
- $CC raft.c -c -D_GNU_SOURCE -DHAVE_LINUX_AIO_ABI_H -Wall -Wextra -Wpedantic -fpic
- $CC raft.c -c -D_GNU_SOURCE $([ $TRAVIS_OS_NAME != 'linux' ] || echo '-DHAVE_LINUX_AIO_ABI_H') -Wall -Wextra -Wpedantic -fpic $UV_CFLAGS
- ./test/lib/fs.sh setup
- make check CFLAGS=-O0 $(./test/lib/fs.sh detect) || (cat ./test-suite.log && false)
- travis_wait 30 make check CFLAGS=-O0 $(./test/lib/fs.sh detect) || (cat ./test-suite.log && false)
- if [ $TRAVIS_COMPILER = gcc ]; then make code-coverage-capture; fi
- ./test/lib/fs.sh teardown

Expand Down
4 changes: 4 additions & 0 deletions example/cluster.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
#include <time.h>
#include <unistd.h>

#if defined(__APPLE__) && defined(__MACH__)
#include <signal.h>
#endif

#define N_SERVERS 3 /* Number of servers in the example cluster */

static int ensureDir(const char *dir)
Expand Down
11 changes: 10 additions & 1 deletion src/uv_metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ static int uvMetadataDecode(const void *buf,
uint64_t format;
format = byteGet64(&cursor);
if (format != UV__DISK_FORMAT) {
#if defined(__FreeBSD__) || defined(__APPLE__)
ErrMsgPrintf(errmsg, "bad format version %llu", format);
#else
ErrMsgPrintf(errmsg, "bad format version %ju", format);
#endif
return RAFT_MALFORMED;
}
metadata->version = byteGet64(&cursor);
Expand Down Expand Up @@ -101,8 +105,13 @@ static int uvMetadataLoadN(const char *dir,
}
return 0;
}
ErrMsgPrintf(errmsg, "%s has size %ju instead of %zu", filename, size,
#if defined(__FreeBSD__) || defined(__APPLE__)
ErrMsgPrintf(errmsg, "%s has size %lld instead of %zu", filename, size,
sizeof content);
#else
ErrMsgPrintf(errmsg, "%s has size %jd instead of %zu", filename, size,
sizeof content);
#endif
return RAFT_CORRUPT;
}

Expand Down
29 changes: 21 additions & 8 deletions src/uv_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,11 @@ static int uvOsFallocateEmulation(int fd, off_t offset, off_t len)
for (offset += (len - 1) % increment; len > 0; offset += increment) {
len -= increment;
rv = (int)pwrite(fd, "", 1, offset);
if (rv != 1)
if (rv != 1) {
if (errno == ENOSPC)
return UV_ENOSPC;
return errno;
}
}

return 0;
Expand All @@ -95,6 +98,22 @@ int UvOsFallocate(uv_file fd, off_t offset, off_t len)
int rv;
#ifdef __linux__
rv = posix_fallocate(fd, offset, len);
#else // MacOS
fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, offset, len, -1};
rv = fcntl(fd, F_PREALLOCATE, &store);
if (-1 == rv) {
// Perhaps we are too fragmented, allocate non-continuous
store.fst_flags = F_ALLOCATEALL;
rv = fcntl(fd, F_PREALLOCATE, &store);
if (-1 == rv) {
rv = EOPNOTSUPP;
if (errno == ENOSPC)
return UV_ENOSPC;
}
} else {
rv = ftruncate(fd, len);
}
#endif
if (rv != 0) {
/* From the manual page:
*
Expand All @@ -104,18 +123,12 @@ int UvOsFallocate(uv_file fd, off_t offset, off_t len)
if (rv != EOPNOTSUPP) {
return -rv;
}
#endif
/* This might be a libc implementation (e.g. musl) that doesn't
* implement a transparent fallback if fallocate() is not supported
* by the underlying file system. */
rv = uvOsFallocateEmulation(fd, offset, len);
if (rv != 0) {
return -EOPNOTSUPP;
}
#ifdef __linux__
}
#endif
return 0;
return rv;
}
#endif

Expand Down
8 changes: 8 additions & 0 deletions src/uv_segment.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,11 @@ int uvSegmentLoadClosed(struct uv *uv,
goto err;
}
if (format != UV__DISK_FORMAT) {
#if defined(__FreeBSD__) || defined(__APPLE__)
ErrMsgPrintf(uv->io->errmsg, "unexpected format version %llu", format);
#else
ErrMsgPrintf(uv->io->errmsg, "unexpected format version %ju", format);
#endif
rv = RAFT_CORRUPT;
goto err_after_read;
}
Expand Down Expand Up @@ -524,7 +528,11 @@ static int uvLoadOpenSegment(struct uv *uv,
goto done;
}
}
#if defined(__FreeBSD__) || defined(__APPLE__)
ErrMsgPrintf(uv->io->errmsg, "unexpected format version %llu", format);
#else
ErrMsgPrintf(uv->io->errmsg, "unexpected format version %ju", format);
#endif
rv = RAFT_CORRUPT;
goto err_after_read;
}
Expand Down
2 changes: 1 addition & 1 deletion test/integration/test_heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@ TEST(raft_heap, aligned_alloc, NULL, NULL, 0, NULL)
p = raft_aligned_alloc(1024, 2048);
munit_assert_ptr_not_null(p);
munit_assert_int((uintptr_t)p % 1024, ==, 0);
raft_free(p);
raft_aligned_free(1024, p);
return MUNIT_OK;
}
14 changes: 14 additions & 0 deletions test/integration/test_uv_append.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,7 @@ TEST(append, noSpaceResolved, setUp, tearDownDeps, 0, DirTmpfsParams)
/* An error occurs while performing a write. */
TEST(append, writeError, setUp, tearDown, 0, NULL)
{
#ifdef __linux__
struct fixture *f = data;
aio_context_t ctx = 0;

Expand All @@ -499,6 +500,12 @@ TEST(append, writeError, setUp, tearDown, 0, NULL)
APPEND_WAIT(0);
AioDestroy(ctx);
return MUNIT_OK;
#elif defined(__FreeBSD__) || defined(__APPLE__)
return MUNIT_SKIP; // AIO not supported
#else
munit_error("Required to implement");
return MUNIT_ERROR;
#endif
}

static char *oomHeapFaultDelay[] = {"1", /* FIXME "2", */ NULL};
Expand Down Expand Up @@ -578,6 +585,7 @@ TEST(append, currentSegment, setUp, tearDownDeps, 0, NULL)
/* The kernel has ran out of available AIO events. */
TEST(append, ioSetupError, setUp, tearDown, 0, NULL)
{
#ifdef __linux__
struct fixture *f = data;
aio_context_t ctx = 0;
int rv;
Expand All @@ -588,6 +596,12 @@ TEST(append, ioSetupError, setUp, tearDown, 0, NULL)
APPEND_FAILURE(1, 64, RAFT_TOOMANY,
"setup writer for open-1: AIO events user limit exceeded");
return MUNIT_OK;
#elif defined(__FreeBSD__) || defined(__APPLE__)
return MUNIT_SKIP; // AIO not supported
#else
munit_error("Required to implement");
return MUNIT_ERROR;
#endif
}

/*===========================================================================
Expand Down
25 changes: 25 additions & 0 deletions test/integration/test_uv_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,11 @@ TEST(load, manySnapshots, setUp, tearDown, 0, NULL)
* before it could complete writing it. */
uv_update_time(&f->loop);
now = uv_now(&f->loop);
#if defined(__FreeBSD__) || defined(__APPLE__)
sprintf(filename, "snapshot-1-8-%llu", now);
#else
sprintf(filename, "snapshot-1-8-%ju", now);
#endif
SNAPSHOT_PUT(1, 8, 1);
DirRemoveFile(f->dir, filename);

Expand Down Expand Up @@ -702,7 +706,11 @@ TEST(load, emptySnapshot, setUp, tearDown, 0, NULL)
* of space before it could write it. */
uv_update_time(&f->loop);
now = uv_now(&f->loop);
#if defined(__FreeBSD__) || defined(__APPLE__)
sprintf(filename, "snapshot-2-6-%llu", now);
#else
sprintf(filename, "snapshot-2-6-%ju", now);
#endif
SNAPSHOT_PUT(2, 6, 2);
DirTruncateFile(f->dir, filename, 0);

Expand Down Expand Up @@ -738,17 +746,27 @@ TEST(load, orphanedSnapshotFiles, setUp, tearDown, 0, NULL)

/* Take a snapshot but then remove the data file, as if the server crashed
* before it could complete writing it. */
#if defined(__FreeBSD__) || defined(__APPLE__)
sprintf(filename1_removed, "snapshot-2-18-%llu", now);
sprintf(metafilename1_removed, "snapshot-2-18-%llu%s", now, UV__SNAPSHOT_META_SUFFIX);
#else
sprintf(filename1_removed, "snapshot-2-18-%ju", now);
sprintf(metafilename1_removed, "snapshot-2-18-%ju%s", now, UV__SNAPSHOT_META_SUFFIX);
#endif
SNAPSHOT_PUT(2, 18, 1);
munit_assert_true(DirHasFile(f->dir, filename1_removed));
munit_assert_true(DirHasFile(f->dir, metafilename1_removed));
DirRemoveFile(f->dir, filename1_removed);

/* Take a snapshot but then remove the .meta file */
now = uv_now(&f->loop);
#if defined(__FreeBSD__) || defined(__APPLE__)
sprintf(filename2_removed, "snapshot-2-19-%llu", now);
sprintf(metafilename2_removed, "snapshot-2-19-%llu%s", now, UV__SNAPSHOT_META_SUFFIX);
#else
sprintf(filename2_removed, "snapshot-2-19-%ju", now);
sprintf(metafilename2_removed, "snapshot-2-19-%ju%s", now, UV__SNAPSHOT_META_SUFFIX);
#endif
SNAPSHOT_PUT(2, 19, 2);
munit_assert_true(DirHasFile(f->dir, filename2_removed));
munit_assert_true(DirHasFile(f->dir, metafilename2_removed));
Expand Down Expand Up @@ -910,10 +928,17 @@ TEST(load, closedSegmentWithEntriesPastSnapshot, setUp, tearDown, 0, NULL)
APPEND(1, 5);
uv_update_time(&f->loop);
now = uv_now(&f->loop);
#if defined(__FreeBSD__) || defined(__APPLE__)
sprintf(errmsg,
"closed segment 0000000000000006-0000000000000006 is past last "
"snapshot snapshot-1-4-%llu",
now);
#else
sprintf(errmsg,
"closed segment 0000000000000006-0000000000000006 is past last "
"snapshot snapshot-1-4-%ju",
now);
#endif
SNAPSHOT_PUT(1, 4, 1);
DirRemoveFile(f->dir, CLOSED_SEGMENT_FILENAME(1, 5));
LOAD_ERROR(RAFT_CORRUPT, errmsg);
Expand Down
2 changes: 2 additions & 0 deletions test/lib/aio.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <sys/syscall.h>
#include <unistd.h>

#ifdef __linux__
#include "munit.h"

int AioFill(aio_context_t *ctx, unsigned n)
Expand Down Expand Up @@ -56,3 +57,4 @@ void AioDestroy(aio_context_t ctx)
rv = syscall(__NR_io_destroy, ctx);
munit_assert_int(rv, ==, 0);
}
#endif
2 changes: 2 additions & 0 deletions test/lib/aio.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#ifndef TEST_AIO_H
#define TEST_AIO_H

#ifdef __linux__
#include <linux/aio_abi.h>

/* Fill the AIO subsystem resources by allocating a lot of events to the given
Expand All @@ -15,5 +16,6 @@ int AioFill(aio_context_t *ctx, unsigned n);

/* Destroy the given AIO context. */
void AioDestroy(aio_context_t ctx);
#endif

#endif /* TEST_AIO_H */
26 changes: 24 additions & 2 deletions test/lib/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@

#define TEST_DIR_TEMPLATE "./tmp/%s/raft-test-XXXXXX"

static char *dirAll[] = {"tmpfs", "ext4", "btrfs", "xfs", "zfs", NULL};
static char *dirAll[] = {"tmpfs", "ext4", "btrfs", "xfs", "zfs", "hfs", NULL};

static char *dirTmpfs[] = {"tmpfs", NULL};

static char *dirAio[] = {"btrfs", "ext4", "xfs", NULL};

static char *dirNoAio[] = {"tmpfs", "zfs", NULL};
static char *dirNoAio[] = {"tmpfs", "zfs", "hfs", NULL};

MunitParameterEnum DirTmpfsParams[] = {
{DIR_FS_PARAM, dirTmpfs},
Expand Down Expand Up @@ -75,6 +75,8 @@ void *DirSetUp(MUNIT_UNUSED const MunitParameter params[],
return DirZfsSetUp(params, user_data);
} else if (strcmp(fs, "xfs") == 0) {
return DirXfsSetUp(params, user_data);
} else if (strcmp(fs, "hfs") == 0) {
return DirHfsSetUp(params, user_data);
}
munit_errorf("Unsupported file system %s", fs);
return NULL;
Expand Down Expand Up @@ -110,6 +112,12 @@ void *DirXfsSetUp(MUNIT_UNUSED const MunitParameter params[],
return dirMakeTemp(getenv("RAFT_TMP_XFS"));
}

void *DirHfsSetUp(MUNIT_UNUSED const MunitParameter params[],
MUNIT_UNUSED void *user_data)
{
return dirMakeTemp(getenv("RAFT_TMP_HFS"));
}

/* Wrapper around remove(), compatible with ntfw. */
static int dirRemoveFn(const char *path,
MUNIT_UNUSED const struct stat *sbuf,
Expand Down Expand Up @@ -397,7 +405,21 @@ void DirFill(const char *dir, const size_t n)
fd = open(path, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
munit_assert_int(fd, !=, -1);

#ifdef __linux__
rv = posix_fallocate(fd, 0, size - n);
#else // MacOS
// Try to get a continous chunk of disk space
fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, size - n, -1};
rv = fcntl(fd, F_PREALLOCATE, &store);
if (-1 == rv) {
// Perhaps we are too fragmented, allocate non-continuous
store.fst_flags = F_ALLOCATEALL;
rv = fcntl(fd, F_PREALLOCATE, &store);
if (-1 == rv)
false;
}
rv = ftruncate(fd, size - n);
#endif
munit_assert_int(rv, ==, 0);

/* If n is zero, make sure any further write fails with ENOSPC */
Expand Down
6 changes: 6 additions & 0 deletions test/lib/dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ void *DirZfsSetUp(const MunitParameter params[], void *user_data);
* system is available. */
void *DirXfsSetUp(const MunitParameter params[], void *user_data);

/* Create a temporary test directory backed by hfs.
*
* Return a pointer the path of the created directory, or NULL if no hfs file
* system is available. */
void *DirHfsSetUp(const MunitParameter params[], void *user_data);

/* Recursively remove a temporary directory. */
void DirTearDown(void *data);

Expand Down
Loading

0 comments on commit 4bfa80a

Please sign in to comment.