Skip to content

Instantly share code, notes, and snippets.

@rampion
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rampion/0233cf60c96dcc0220d8 to your computer and use it in GitHub Desktop.
Save rampion/0233cf60c96dcc0220d8 to your computer and use it in GitHub Desktop.
for some reason, I was tempted to play with dependency injection in C
#include "depinjex.h"
#include <stdlib.h>
#include <stdio.h>
#ifdef ENABLE_DEPENDENCY_INJECTION
depinjex_dependencies_t depinjex_dependencies = {
._atoi = atoi,
._fprintf = fprintf,
._fizzbuzz_main = fizzbuzz_main,
._fizzbuzz_loop = fizzbuzz_loop,
._fizzbuzz = fizzbuzz
};
# define _(f, ...) depinjex_dependencies._ ## f __VA_ARGS__
#else
# define _(f, ...) f __VA_ARGS__
#endif // ENABLE_DEPENDENCY_INJECTION
int fizzbuzz_main(int argc, char **argv) {
int const max = (argc == 2 ? _( atoi,(argv[1]) ) : 100);
_( fizzbuzz_loop,(max) ) ;
return 0;
}
void fizzbuzz_loop(int max) {
for (int i = 1; i <= max; i++) {
_( fizzbuzz,(i) );
}
}
void fizzbuzz(int n) {
static char * fmt[4] = { "%d\n", "fizz\n", "buzz\n", "fizzbuzz\n" };
_( fprintf,(_(stdout), fmt[ 2 * (n % 5 == 0) + (n % 3 == 0) ], n) );
}
#ifndef DEPINJEX_H
#define DEPINJEX_H
int fizzbuzz_main(int argc, char **argv);
void fizzbuzz_loop(int max);
void fizzbuzz(int n);
#ifdef ENABLE_DEPENDENCY_INJECTION
#include <stdio.h>
typedef struct {
int (*_atoi)(const char *str);
int (*_fprintf)(FILE *out, char const *fmt, ...);
FILE *_stdout; // must be initialized at runtime
int (*_fizzbuzz_main)(int argc, char **argv);
void (*_fizzbuzz_loop)(int max);
void (*_fizzbuzz)(int n);
} depinjex_dependencies_t;
depinjex_dependencies_t depinjex_dependencies;
#endif // ENABLE_DEPENDENCY_INJECTION
#endif // DEPINJEX_H
#include "depinjex.h"
int main(int argc, char **argv){
return fizzbuzz_main(argc,argv);
}
fizzbuzz: depinjex.c main.c
gcc -o $@ $^
fizzbuzz-test: depinjex.c test.c
gcc -DENABLE_DEPENDENCY_INJECTION -o $@ $^
test: fizzbuzz-test
./$^
clean:
rm -f *.o fizzbuzz fizzbuzz-test
#include "depinjex.h"
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
int main(int argc, char**argv){
// setup fake stdout
int stdout_pair[2] = {};
pipe(stdout_pair);
FILE * stdout_read = fdopen(stdout_pair[0], "r");
FILE * stdout_write = fdopen(stdout_pair[1], "w");
// use fake stdout in fizzbuzz_main
depinjex_dependencies._stdout = stdout_write;
// check return status of fizzbuzz_main
char * test_argv[2] = { "fizzbuzz", "5" };
assert( 0 == fizzbuzz_main(2, test_argv) );
// check output from fizzbuzz_main
char const * expected = "1\n2\nfizz\n4\nbuzz\n";
fclose(stdout_write);
for (;*expected;expected++) {
assert( *expected == fgetc(stdout_read) );
}
assert( EOF == fgetc(stdout_read) );
fclose(stdout_read);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment