Checking IBOutlet connection with OCMock - unit-testing

I want to verify with unit tests that all the IBoutlets in my controller class are correctly hooked up in the NIB file. I'd like to do this with OCMock - even though I know I could simply assert the controllers variables are not nil after loading the NIB. This is more a matter of general understanding of how the process works - as far as I understand it, this should be working, too.
The NIB OnOffSwitchCell has as its File's Owner OnOffSwitchCellController.
This is my test method:
- (void) testIBOutletCellIsWiredToXib {
id mockController = [OCMockObject mockForClass:[OnOffSwitchCellController class]];
[[mockController expect] awakeAfterUsingCoder:OCMOCK_ANY];
[[mockController expect] setValue:OCMOCK_ANY forKey:#"cell"];
[[mockController expect] setValue:OCMOCK_ANY forKey:#"thelabel"];
[[mockController expect] setValue:OCMOCK_ANY forKey:#"theswitch"];
NSArray* nibContents = [guiBundle loadNibNamed:#"OnOffSwitchCell"
owner:mockController
options:nil];
assertThat(nibContents, isNot(nil));
assertThatInt([nibContents count], is(equalToInt(1)));
assertThat([nibContents objectAtIndex:0], is(instanceOf([OnOffSwitchCell class])));
[mockController verify];
}
guiBundle exists and is verified to be a valid NSBundle object.
From what I understand loadNibNamed:owner:options: will deserialize the objects in the NIB, call awakeAfterUsingCoder: and then set the outlets by calling setValue:forKey: for each one.
I put in three more asserts to make sure the loaded NIB actually contains the correct objects - these pass OK when I put in an instance of the real controller. But when I use the mock as shown above, it does not even get this far. Instead, the test crashes with this:
Test Case '-[OnOffSwitchCellControllerTestCase testIBOutletCellIsWiredToXib]' started.
2011-01-14 10:48:35.364 GTMTest[67797:903] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'OCMockObject[OnOffSwitchCellController]:
unexpected method invoked: awakeAfterUsingCoder:<UINibDecoder: 0x500e800>
expected: setValue:<OCMAnyConstraint: 0x4c718e0> forKey:#"cell"
expected: setValue:<OCMAnyConstraint: 0x4c71ce0> forKey:#"thelabel"
expected: setValue:<OCMAnyConstraint: 0x4c71ed0> forKey:#"theswitch"'
*** Call stack at first throw:
(
0 CoreFoundation 0x00e3dbe9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x00f925c2 objc_exception_throw + 47
2 CoreFoundation 0x00e3db21 -[NSException raise] + 17
3 GTMTest 0x0001a049 -[OCMockObject handleUnRecordedInvocation:] + 322
4 GTMTest 0x00019aca -[OCMockObject forwardInvocation:] + 77
5 CoreFoundation 0x00daf404 ___forwarding___ + 1124
6 CoreFoundation 0x00daef22 _CF_forwarding_prep_0 + 50
7 UIKit 0x0062394a UINibDecoderDecodeObjectForValue + 2438
8 UIKit 0x00624693 -[UINibDecoder decodeObjectForKey:] + 398
9 UIKit 0x0053cf43 -[UIRuntimeConnection initWithCoder:] + 212
10 UIKit 0x0053d4b1 -[UIRuntimeEventConnection initWithCoder:] + 64
11 UIKit 0x006239e4 UINibDecoderDecodeObjectForValue + 2592
12 UIKit 0x006232dc UINibDecoderDecodeObjectForValue + 792
13 UIKit 0x00624693 -[UINibDecoder decodeObjectForKey:] + 398
14 UIKit 0x0053c200 -[UINib instantiateWithOwner:options:] + 804
15 UIKit 0x0053e081 -[NSBundle(UINSBundleAdditions) loadNibNamed:owner:options:] + 168
16 GTMTest 0x000140dc -[OnOffSwitchCellControllerTestCase testIBOutletCellIsWiredToXib] + 503
17 GTMTest 0x000041f3 -[SenTestCase invokeTest] + 163
18 GTMTest 0x0000479a -[GTMTestCase invokeTest] + 146
19 GTMTest 0x00003e90 -[SenTestCase performTest] + 37
20 GTMTest 0x00002f3d -[GTMIPhoneUnitTestDelegate runTests] + 1413
21 GTMTest 0x000028fb -[GTMIPhoneUnitTestDelegate applicationDidFinishLaunching:] + 197
22 UIKit 0x00347253 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1252
23 UIKit 0x0034955e -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 439
24 UIKit 0x00348ef0 -[UIApplication _run] + 452
25 UIKit 0x0035542e UIApplicationMain + 1160
26 GTMTest 0x00003500 main + 104
27 GTMTest 0x0000273d start + 53
28 ??? 0x00000002 0x0 + 2
)
terminate called after throwing an instance of 'NSException'
So it is complaining the call to awakeAfterUsingCoder: as being unexpected, even though I clearly expected it.
I also tried removing that expectation and replacing the mock with a nice mock that will not report superfluous method calls, but then it still aborts and reports the setValue:forKey: not being called.
What am I missing here?

Have you tried running this on the main system thread? You cannot instance UIKit classes off the main thread. Not sure how GTM does it, but with GHUnit you can put the following into your test case class:
- (BOOL)shouldRunOnMainThread {
/* Tell GHUnit to run on a separate thread */
return YES;
}

you cant actually do any visual stuff in unit tests. The views are never actually loaded. Also, you dont need to test that awakeAfterUsingCoder is invoked. Thats Apple's stuff. Typically your unit tests must only test your logic. You can safely assume that awakeAfterUsingCoder is invoked from init, because it's Apple's code. You just need to make sure your methods are invoked

Related

happy base integration not working with hbase

I am able to connect with my hbase
connection = happybase.Connection(host='node-04',port=16000)
table = connection.table('test')
These 2 commands work without any error. but when I run the below cammand i am getting following error
print connection.tables()
error
Traceback (most recent call last)
<ipython-input-49-de0848d7286f> in <module>()
----> 1 print connection.tables()
/root/anaconda2/lib/python2.7/site-packages/happybase/connection.pyc in tables(self)
236 :rtype: List of strings
237 """
--> 238 names = self.client.getTableNames()
239
240 # Filter using prefix, and strip prefix from names
/root/anaconda2/lib/python2.7/site-packages/happybase/hbase/Hbase.pyc in getTableNames(self)
815 #return returns a list of names
816 """
--> 817 self.send_getTableNames()
818 return self.recv_getTableNames()
819
/root/anaconda2/lib/python2.7/site-packages/happybase/hbase/Hbase.pyc in send_getTableNames(self)
823 args.write(self._oprot)
824 self._oprot.writeMessageEnd()
--> 825 self._oprot.trans.flush()
826
827 def recv_getTableNames(self, ):
/root/anaconda2/lib/python2.7/site-packages/thrift/transport/TTransport.pyc in flush(self)
172 # reset wbuf before write/flush to preserve state on underlying failure
173 self.__wbuf = StringIO()
--> 174 self.__trans.write(out)
175 self.__trans.flush()
176
/root/anaconda2/lib/python2.7/site-packages/thrift/transport/TSocket.pyc in write(self, buff)
128 have = len(buff)
129 while sent < have:
--> 130 plus = self.handle.send(buff)
131 if plus == 0:
132 raise TTransportException(type=TTransportException.END_OF_FILE,
error: [Errno 32] Broken pipe
I am usingHbase version:1.1.2.2.3.4.0-3485
Please help if you can suggest any package which i can use to code for hbase using python
happybase requires you to connect to the thrift daemon, which you need to start on your hbase cluster. happybase does not connect to hbase nodes directly.
judging from the port number, you are not connecting to thrift (uses port 9090 by default) but to the hbase master. this is not how happybase works.

Cocos2D V3.0 crash CCLabelTTF

I am converting my project from using Cocos2D v2.1 to V3.0. It's a UIKit project with Cocos2D added as a sub-project and the director loaded lazily in a couple of viewcontrollers.
I managed to get rid of all the compiler warnings, it runs fine and seems to load the director fine, but then crashes as follows:
-[NSConcreteMutableAttributedString hasAttribute:]: unrecognized selector sent to instance 0xc4f8ff0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSConcreteMutableAttributedString hasAttribute:]: unrecognized selector sent to instance 0xc4f8ff0'
*** First throw call stack:
(
0 CoreFoundation 0x0291a1e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x026998e5 objc_exception_throw + 44
2 CoreFoundation 0x029b7243 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x0290a50b ___forwarding___ + 1019
4 CoreFoundation 0x0290a0ee _CF_forwarding_prep_0 + 14
5 0x0019d7d0 -[CCLabelTTF updateTexture] + 544
6 0x0019d546 -[CCLabelTTF visit] + 70
7 0x00181c86 -[CCNode visit] + 566
8 0x00181c86 -[CCNode visit] + 566
9 0x00202b9d -[CCDirectorIOS drawScene] + 381
10 0x00203fdc -[CCDirectorDisplayLink mainLoop:] + 92
The breakpoint stops in the CCLabelTTF function - (BOOL) updateTexture at
#ifdef __CC_PLATFORM_IOS
// Font color
if (![formattedAttributedString hasAttribute:NSForegroundColorAttributeName])
There is only one CCLabelTTF in the code, and I create it like so:
self.scoreLabel = [CCLabelTTF labelWithString:NSLocalizedString(#"Score", #"") fontName:#"Marker Felt" fontSize:20 dimensions:CGSizeMake(100, 50)];
self.scoreLabel.horizontalAlignment = (CCTextAlignment)NSTextAlignmentRight;
scoreLabel.position = ccp(250,70);
[self addChild:scoreLabel z:1];
Any help much appreciated. I've searched Cocos2D forums and here and can't find anything similar to this issue.
Ahh... just solved it. Since Cocos2d is a sub-project, I had to include the -ObjC flag under Other Linker Flags for the target. This wasn't necessary with v2.1, but then that version didn't use the NSAttributedString+CCAdditions category.

logback skipping log files on AWS EC2

I'm using logback for logging from an app deployed in Tomcat, with a fairly simple setup (see code fragments). We use a RollingFileAppender, with TimeBasedRollingPolicy, set for daily rollover. When running locally, everything appears to be fine. When running in AWS in an EC2 instance, I'm seeing that some log files are missing.
I wrote a really simple app that does nothing but log once per second with a counter, and then a logback config that rolls every minute. For this particular test, we're seeing every third log file is missing.
So, for example, we'll get:
-rw-r--r-- 1 tomcat tomcat 891 May 13 18:46 logtest_tomcat.2014-05-13_1845.0.log.gz
-rw-r--r-- 1 tomcat tomcat 499 May 13 18:47 logtest_tomcat.2014-05-13_1846.0.log.gz
-rw-r--r-- 1 tomcat tomcat 541 May 13 18:49 logtest_tomcat.2014-05-13_1848.0.log.gz
-rw-r--r-- 1 tomcat tomcat 519 May 13 18:50 logtest_tomcat.2014-05-13_1849.0.log.gz
-rw-r--r-- 1 tomcat tomcat 532 May 13 18:52 logtest_tomcat.2014-05-13_1851.0.log.gz
-rw-r--r-- 1 tomcat tomcat 510 May 13 18:53 logtest_tomcat.2014-05-13_1852.0.log.gz
-rw-r--r-- 1 tomcat tomcat 536 May 13 18:55 logtest_tomcat.2014-05-13_1854.0.log.gz
-rw-r--r-- 1 tomcat tomcat 1226 May 13 18:56 logtest_tomcat.2014-05-13_1855.0.log.gz
-rw-r--r-- 1 tomcat tomcat 531 May 13 18:58 logtest_tomcat.2014-05-13_1857.0.log.gz
-rw-r--r-- 1 tomcat tomcat 496 May 13 18:59 logtest_tomcat.2014-05-13_1858.0.log.gz
-rw-r--r-- 1 tomcat tomcat 1244 May 13 19:01 logtest_tomcat.2014-05-13_1900.0.log.gz
-rw-r--r-- 1 tomcat tomcat 496 May 13 19:02 logtest_tomcat.2014-05-13_1901.0.log.gz
-rw-r--r-- 1 tomcat tomcat 514 May 13 19:04 logtest_tomcat.2014-05-13_1903.0.log.gz
-rw-r--r-- 1 tomcat tomcat 500 May 13 19:05 logtest_tomcat.2014-05-13_1904.0.log.gz
-rw-r--r-- 1 tomcat tomcat 522 May 13 19:07 logtest_tomcat.2014-05-13_1906.0.log.gz
The file format is yyyy-mm-dd_HHmm - so you can see that 1847, 1850, 1853, 1856, 1859, 1902, 1905 are all missing.
I've checked the contents - the sequential numbering on the log statements jumps by 60 for the missing logs - so it's not that multiple minutes are being collapsed into a single rolled over log.
We also thought it might be due to our Splunk forwarder - we ran the test both with and without the Splunk forwarder running, and got the same results - every third log file is missing.
Here's the logback appender for this test:
<appender name="daily" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${bc.logs.home}/logtest_tomcat.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- Rollover every minute for this test -->
<fileNamePattern>${bc.logs.home}/logtest_tomcat.%d{yyyy-MM-dd_HHmm}.%i.log.gz</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- or whenever the file size reaches 250MB -->
<maxFileSize>250MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>60</maxHistory>
</rollingPolicy>
<append>true</append>
<encoder>
<pattern>%d{"yyyy-MM-dd HH:mm:ss,SSS z", UTC} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
And here's my little driver class (the 'BCLog' is a simple wrapper around slf4j logging, instantiated by
Logger log = LoggerFactory.getLogger(clazz);
)
package com.sirsidynix.logtest.biz.svc.impl;
import com.sirsidynix.bccommon.util.BCLog;
import com.sirsidynix.bccommon.util.BCLogFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class JustLogIt implements InitializingBean, DisposableBean
{
private static final BCLog LOG = BCLogFactory.getLog(JustLogIt.class);
private Thread thread;
#Override
public void afterPropertiesSet() throws Exception
{
LOG.info("Firing up JustLogIt thread");
thread = new Thread(){
#Override
public void run()
{
long iteration = 0;
while (true)
{
try
{
Thread.sleep(1000);
iteration++;
LOG.info("Logging Iteration " + iteration);
}
catch (InterruptedException e)
{
LOG.info("LogIt thread sleep interrupted!!!");
}
}
}
};
thread.start();
}
#Override
public void destroy() throws Exception
{
LOG.info("Shutting down JustLogIt thread");
thread.interrupt();
}
}
Any ideas?
Thanks!

How to configure 'cookie::$salt' in kohana

In this part of the Kohana documentation: (http://kohanaframework.org/3.1/guide/kohana/cookies) it says I can find
Cookie::$salt = 'foobar';
In bootstrap.php.
I don't see it there. Am I just being thick, or is there a better way?
It's not in the bootstrap.php file by default. I've added it to the file, after Kohana::modules and before the routes.
Looks like config updated in the latest version 3.3.4 (at the time of writing)
134 /**
135 * Cookie Salt
136 * #see http://kohanaframework.org/3.3/guide/kohana/cookies
137 *
138 * If you have not defined a cookie salt in your Cookie class then
139 * uncomment the line below and define a preferrably long salt.
140 */
141 // Cookie::$salt = NULL;
142 Cookie::$salt = 'LOASWnL7A1WKQMk1JALCP1H5BMelyIPQNVdXiGsbEEVhVtyApGsFC6LyINUsDHl1';

Destroying client-related data in a multi-client/server system

I will build a multi-client/server system. It's expected to work like this:
The client comunicates with the server using TCP/IP
When the client makes the connection to the server, the client sends a command string. When the server receives the command string, it parses it, do the required work and then sends a response to the client.
When the client closes the TCP connection, the server will destroy the resource related to this client.
The server is a multi-threaded program. The command receive, the command parse, the command deal and the response to the client may each be in a different thread.
Now, I want to define a CmdTcpContext class to contain the data related to the client.
class CmdTcpContext
18 {
19 public:
20 CmdTcpContext(){recv_buff_.SetRecvList(&recv_list_);}
21 ~CmdTcpContext(){}
22
23 CmdRecvBuffer & recv_buff(){return recv_buff_;}
24 SendBuffer & send_buff(){return send_buff_;}
25
26 RecvList<CmdPackage> & recv_list(){return recv_list_;}
27 RecvList<CmdPackage> & send_list(){return send_list_;}
28
29 InetAddr & inet_addr(){return addr_;}
30 SockStream & sock_stream(){return stream_;}
31
32 EventHandler * event_handler(){return handler_;}
33 void event_handler(EventHandler * eh){handler_ = eh;}
34 private:
35 SockStream stream_;
36 InetAddr addr_;
37
38 CmdRecvBuffer recv_buff_;
39 SendBuffer send_buff_;
40
41 RecvList<CmdPackage> recv_list_;
42 RecvList<CmdPackage> send_list_;
43
44 EventHandler *handler_;
45 };
My problem is: how can I destroy the CmdTcpContext object when the client closes the connection?