/*
 * Copyright 2022, ttcoder
 * All rights reserved. Distributed under the terms of the MIT license.
 */


// libc.so
#include <stdio.h>
#include <fcntl.h>  // open() etc

#if hog_TEST_LEVEL >= 6
#	include <app/Application.h>
#	include <app/Messenger.h>
#endif

////////
#define CHECK(x) if(x) { puts( "(pass) " #x ); } else { puts( " ******** FAIL! : " #x ); }



#if 0
//simple testing of Genode's pipes, got me going before doing a full-fledged Broker

void run()
{
	// --- "client" ---
	
	// Tx to "server"
	//
	int tx = open( "/dev/upstream", O_WRONLY );
	CHECK( tx >= 0 );
	CHECK( 3 == write(tx, "123", 3) );
	CHECK( close(tx) == 0 );
	
	// Rx from "server"
	int rx = open( "/dev/downstream", O_RDONLY );
	CHECK( rx >= 0 );
	for( ; ; )
	{
		char buf[256] = {};
		const int got = read( rx, buf, sizeof(buf) );
		
		if( got == 0 )
			break;
		if( got < 0 )
		{
			Genode::error( "rx error: ", got );
			break;
		}
		
		Genode::log( "client rx:", (const char*) buf );/**/
	}
	CHECK( close(rx) == 0 );
}
#endif


int main()
{
#if hog_TEST_LEVEL <= 1
	// jam hog-broker.emu1 (simple test)
	///ToDo: Move that test to hog-test (or to a new "hog-test-advanced.run"), we can no longer run it here since hog-broker cannot run below level 6 any more, since broker uses BMessage et al, so this stuff does not belong here
	run();

#elif hog_TEST_LEVEL >= 6

	// jam hog-broker.emu6 is necessary here (complex test)
	//
	
	// we allow for two numeric values, to avoid timing trouble with 2 components in a race, either of which in a position to get first pick at port number #1000 ; alternatively, we could split the tests, *separate* 1) stand-alone tests (where we are the lone exe, so guaranteed to have pseudo-team == 1 and first port == 1000), from 2) interact-with-registrar tests, where registrar might launch first, and clailm pseudo-team 1 while we clailm pseudo-team 2, and in that latter case lets NOT test port numbers...
	int base_port = create_port( 20, "dummy" );
	CHECK( 1000 == base_port || 2000 == base_port );
/*
	///ToDo: when Application.cpp #define's RUN_WITHOUT_REGISTRAR, or if it tweaks/snooze() (or not) for roster race, we get a related oddity: "vfs" can crash it seems! Related to roster "race" (the crash was observed in a 'run' whereby registrar launched too late, and test_client exited due to that):
		ToDo: investigate vfs crash, lookup the addy with addr2line:
	no RM attachment (WRITE pf_addr=0x1e0ca0 pf_ip=0x10f4de83 from pager_object: pd='init -> vfs' thread='ep') 
	page fault, pd='init -> vfs' thread='ep' cpu=0 ip=0x10f4de83 address=0x1e0ca0 stack pointer=0x401fece0 qualifiers=0x6 irUWp reason=1
*/
	CHECK( base_port +1 == create_port(20, "simple client/IPC test") );
	CHECK(           -1 == find_port("Non-Existent") );
	CHECK( base_port    == find_port("dummy") );
	
	// ! real-ish test: B_REGISTRAR_PORT_NAME:
#if 0
		// handshake done, while creating our very first port! now stall for a bit:
		snooze(999000);  ///give some time for registrar to launch and create its commo port before we access it...
		// (we will never have race issues with Broker/write_port(), since RPC calls for writing to ports will nicely wait for Broker to be up,
		// but we could certainly have a race where we find_port("registrar") and fail because registrar has not started running yet !)
	CHECK( 1002 == create_port(20, "system:roster") );
	CHECK( 1002 == find_port("system:roster") );
	//xx The above is not worth it: subsequent BMessenger() tests below, do write to this *fake* roster port, synchronously waiting for a response that never comes... Better launch the actual roster/registrar and test with its genuine roster port, instead
#endif
	
	// Tx/Rx test, against our own port:
	// (tests LOCAL ports)
	//
	CHECK( B_BAD_PORT_ID == write_port_etc(9999, 0, "foo", 3, 0, 0) );
	;
	CHECK( B_OK == write_port_etc(base_port, 0xfeed, "hello", 5, 0, 0) );
	{
		int32 code = -1;
		char buf[5] = {};
		
		CHECK( 5 == read_port(base_port, &code, buf, 5) );
		CHECK( 0 == memcmp(buf, "hello", 5) );
		CHECK( 0xfeed == code );
	}
	
	// Test against Registrar:
	// (tests REMOTE/global ports)
	//
	BApplication app( "application/x-vnd.test" );  // that will send a 'registration' request to registrar, for that signature
	CHECK( B_OK == app.InitCheck() );
	
	status_t mger_init = 0;
	status_t res =  // this will look-up which team is registered under that MIME signature, in the registrar:
		BMessenger( "application/x-vnd.test", -1, &mger_init )
			.SendMessage( B_ABOUT_REQUESTED );
	CHECK( B_OK == mger_init );
	CHECK( B_OK == res );
	//printf("BMessenger TEST: init=0x%x res=0x%x\n", mger_init, res);
#else
#	error unknown test level
#endif
	
	puts( " -- tests complete -- " );
	
	return 0;
}


