Hello!
I have been learning Erlang, and decided to build a toy interpreter as an exercise.
Then I got confused when trying to implement a symbol table… See what I’ve done so far:
- The symbol table is implementer as an ETS table.
- The interpreter should work with several processes reading and writing the table, so there is one writer (
gen_serverbehavior) which handles all writes and an API for concurrent processes to read and write to the table (a simple module). This API will call the server for writes, and directly read from the table (if N processes try to write, they’ll naturally be serialized because they all call the same server; if N processes try to read, they will use the API simultaneously).
So the problem is… There are two modules (the writer and the symbol table API), and when I started writing the tests, I got stuck: I can;t test the write server alone, so there are these options:
-
Write tests for the write server and check the effect of each message by directly reading the ETS table (but this makes the test implementation dependent): test things like
gen_server:call(symbol_writer,{sym_intern, "symbol_name"}), and then do ets:lookup directly to check the table -
Write tests only for the API, and the server will be indirectly tested (but sounds like a bad idea for testing): test
SymbolId = symbol_table:intern("symbol_name")and then check withets:lookup(symbols, "symbol_name"). -
Write tests for the server, and use the API to check the effect of the writing messages on the table (but testing the server would depend on an external module – the general symbol table API).
gen_server:call(symbol_writer,{sym_inern, "symbol_name"}), and then check withets:lookup(symbols, "symbol_name").
Is the architectural approach OK (having the server do only the writing, to allow for concurrent reading, and do all the interaction through an API)?
If the architecture is OK, how would be the best approach to testing?
Thanks a lot!