Avoiding downcasts in a Swift 3 completion handler with Google Drive REST API - swift3

I'm using the Google Drive REST API in a Swift 3 app. Queries are executed using the executeQuery method of GTLRDriveService. This method takes a completion block of type GTLRServiceCompletionHandler?, which in turn is declared as
public typealias GTLRServiceCompletionHandler = (GTLRServiceTicket, Any?, Error?) -> Swift.Void
Because of this declaration, the second parameter must be downcast to the appropriate type inside the block. For instance:
let createPermissionQuery = GTLRDriveQuery_PermissionsCreate.query(
withObject: permission, fileId: toShare.id)
...
driveService.executeQuery(createPermissionQuery) { (ticket, result, error) in
if (error == nil) {
// need to downcast result to GTLRDrive_Permission
let permission = result as! GTLRDrive_Permission
...
}
}
The second parameter is always of a specific type that is completely determined by the particular query passed to executeQuery. For instance, if one passes an instance of GTLRDriveQuery_PermissionsCreate, then the second parameter (if the query succeeds) will always be of type GTLRDrive_Permission. However, if I try to declare result to be of any type other than Any?, the code won't compile.
In Objective C, the completion block can be specified with a type that's specific to the query. For instance (adapted from here):
GTLRDriveQuery_PermissionsCreate *createPermissionQuery =
[GTLRDriveQuery_PermissionsCreate queryWithObject:permission
fileId:fileId];
...
[driveService executeQuery:createPermissionQuery
completionHandler:^((GTLRServiceTicket *ticket,
GTLRDrive_Permission *permission,
NSError *error) {
if (error == nil) {
// work directly with permission
...
}
}];
Is there any way to avoid this downcast? (I'm asking out of ignorance; I'm somewhat of a newbie to Swift.) If I was writing my own library, I'd design the method signatures differently, but this is Google's library and am kind of stuck with what they supply. Perhaps some sort of extension or layer on top of Google's code?

You might be able to specify an extension that wraps the Google execute method, takes a generic and casts to your generic type in the block. This would basically just be a pretty abstraction of what you're doing already, but for all types your extension would be designed to cover.

Related

Saving objects to UserDefaults that confirm to a protocol(using protocol oriented programming paradigm)

I have multiple object types that I want to save to UserDefaults.So, I have written a UserDefaultsManager class where I have methods to save objects in UserDefaults using NSKeyedArchiver and to fetch using NSKeyedUnarchiver.Here are the methods:
class UserDefaultsManager
{
class func saveToUserDefaults(object:Any, Key:String)
{
let data = NSKeyedArchiver.archivedData(withRootObject: object)
UserDefaults.standard.setValue(data, forKey: key)
UserDefaults.standard.synchronize()
}
class func userDefaultsForKey(_ key:String) -> Any
{
let data = UserDefaults.standard.value(forKey: key)
let object = NSKeyedUnarchiver.unarchiveObject(with: data as! Data)
return object as! LoginUser
}
}
As you can see that objects to be saved can be of any type, so I have defined the parameter as 'Any'. Now while I need to fetch the object, I am down casting it to 'LoginUser' object type and then returning it.
I can also add another parameter called 'type' and based on that I can downcast it to that particular type.But that's not the point here.
The point here is that I was thinking of creating a protocol, say,'UserDefaultsPersistence' and only the classes confirming to that protocol can call such methods and be saved in UserDefaults.Here is an example:
class func archiveObject<T:UserDefaultPersistence>(object:T) -> Data
{
let data = NSKeyedArchiver.archivedData(withRootObject: object)
return data
}
But the problem is that when I fetch the object from UserDefaults,I will have to downcast it to that particular object to use its properties.So what's the whole point of using protocols?
The point of using a protocol would be so the programmer knows which objects are and are not explicitly supported for archiving by the app (although, you can still archive other things). Also, since the method signature enforces conformance to the protocol, you will have to make/declare each object conform to it to be able to use it with those methods. This will make your code easier to understand and more type safe, as it will prevent you from accidentally trying to archive or unarchive something which you don't explicitly support.
If you are supporting many objects being archived, I would assume using Core Data would be a better option. In the short term, it will take some time to get set up, but in the long run it will save you time, since you will have access to a strongly typed database. UserDefaults is really for simple things and is not meant to replace a database.

Is there a cleaner way to test functions that use functions that require user input in Rust?

I am writing a CLI question asking library for my first Rust project since I will probably be using it anyway, and I cannot find a clean way to test the terminal method of the builder pattern, which using the configuration gets user input and returns an answer.
pub fn confirm(&mut self) -> Answer {
self.yes_no();
self.build_prompt();
let prompt = self.prompt.clone();
let valid_responses = self.valid_responses.clone().unwrap();
loop {
let stdio = io::stdin();
let input = stdio.lock();
let output = io::stdout();
if let Ok(response) = prompt_user(input, output, &prompt) {
for key in valid_responses.keys() {
if *response.trim().to_lowercase() == *key {
return valid_responses.get(key).unwrap().clone();
}
}
self.build_clarification();
}
}
}
Looking for a solution I discovered dependency injection which allowed me to write tests for the function that prompts the user for input using Cursor. It does not let me change the user input to the confirm() function for each test of Question::new("Continue?").confirm() though so I tried using conditional compilation, and came up with the following.
#[cfg(not(test))]
fn prompt_user<R, W>(mut reader: R, mut writer: W, question: &str) -> Result<String, std::io::Error>
where
R: BufRead,
W: Write,
{
write!(&mut writer, "{}", question)?;
let mut s = String::new();
reader.read_line(&mut s)?;
Ok(s)
}
#[cfg(test)]
fn prompt_user<R, W>(mut reader: R, mut writer: W, question: &str) -> Result<String, std::io::Error>
where
R: BufRead,
W: Write,
{
use tests;
Ok(unsafe { tests::test_response.to_string() })
}
And in the tests module I use a global variable:
pub static mut test_response: &str = "";
#[test]
fn simple_confirm() {
unsafe { test_response = "y" };
let answer = Question::new("Continue?").confirm();
assert_eq!(Answer::YES, answer);
}
This works as long as I only run tests with a single thread, but also no longer allows me to test the real user input function. Not really a problem for such a small crate but it is very messy. I did not see any solutions to do this from any available testing libraries.
As mentioned in the Stack Overflow question you linked, you should generally avoid hard-wiring external dependencies (a.k.a. I/O) if you want testability:
disk access,
terminal access,
network access,
database access,
time access.
In all such cases, I recommend using Dependency Injection:
create a clean interface (trait) to describe the allowed actions (don't overdo it, YAGNI!),
implement the interface for "production" use, with the real external dependency behind it,
implement a "mock" of the interface for "test" use.
Then, when writing:
a function which requires access to this resource, pass it as argument,
a method which requires access to this resource, pass it as either argument or in the constructor of the object.
Finally, instantiate the production dependencies in main, and forward them from there.
Tricks, not treats:
It may be useful to create an Environment structure which contains all such interfaces, rather than passing heaps of arguments to each function; however functions which only require one/two resource(s) should take those explicitly to make it clear what they use,
I have found it useful to pass the timestamp rather than the clock from which it is obtained in the past... just because multiple calls to now() may return different results as the time passes.

Setting up setCharging for Linea Pro device in Swift

I want to set up the Linea Pro to charge the phone if the phone's battery gets low and I'm having a tough time mainly because all the examples are shown in objective-C still and not in Swift.
The manual says:
#param enabled TRUE to enable charging, FALSE to disable/stop it
#param error pointer to NSError object, where error information is stored in case function fails. You can pass nil if you don't want that information
#return TRUE if function succeeded, FALSE otherwise
*/
and the code provided is the following:
-(BOOL)setCharging:(BOOL)enabled error:(NSError **)error;
So in Swift I first tried this:
self.scanner.setCharging = true
but that gives me the following error:
Cannot assign to property: 'setCharging' is a method
So I tried this:
self.scanner.setCharging(true)
which gives me this error:
Call can throw, but it is not marked with 'try' and the error is not handled
Interesting because apparently I have to build it in a function called "setCharging" I think, but I have no idea what and how it wants me to set up the try and catch to, and quite frankly where am I opposed to get this information from?
I think it should be along these lines or something, but I'm not clear on the specifics :
func setCharging(_ enabled: Bool) throws -> Bool {
do {
try
//something goes here I'm not sure what
} catch {
//and then maybe something here on that to do with error
print("some error")
}
}
The answer was provided to me by the manufacturer. It is unnecessary to create a function with the same name as the API, APIs can be called anywhere in the code with the exception of handling error. So in this case I just have this directly in my code not in a function and it just works. (Since I have my scanner.connect code inside a viewWillAppear block, the code to start charging was too early to be called in there, so I placed it inside of a viewDidAppear block).
The following is the code:
do{
try self.scanner.setCharging(true)
}catch let error as NSError{
NSLog("Operation \(error as Error)")
}

Request context in a Go template

I would like to write such a conditional fragment in a Go HTML template :
{{if isUserAdmin}}
<a href"/admin/nuke">Go to the big red nuclear button</a>
{{end}}
However, this is not directly possible because the template is not aware of the request that triggered its execution, so it cannot determine if the user is admin or not.
Is there some normal way to achieve this ?
In advance I point out that :
I do not want to use Pipelines for this specific data (see other question about this)
I acknowledge that only the handlers/controllers should deal with logic, and views should only do the rendering. But the condition {{if isUserAdmin}} is not logic itself, it's a necessary construct to leverage a boolean value already calculated by the controller.
The Funcs method can help, but is currently not lean enough for easily defining specific method isUserAdmin()
I would agree with Darshan Computing, I think the proper way of passing information from the request would be in the pipeline. You can have your data being split between the data you want to render and the context, e.g. by having your template data structure embed them both if you want to clearly separate the two:
type TemplateData struct {
*Content
*Context
}
Which gives this for example. You can then reuse some of your context/content information depending on what is shared and what is query specific.
Here is a working solution attempt (link to Playground) using Funcs to overwrite "isAdmin", after template compilation but before each execution (thanks to Valentin CLEMENT in other question).
But it has several flaws :
It is weird to declare a dummy empty "isAdmin" function before template compilation.
(Using Funcs several times is painful because I cannot just overwrite a single method, I have to provide a complete FuncMap with all the functions) edit : in fact previous funcs are not lost, i was wrong about that.
It is inherently not thread-safe and will fail when several goroutines alter and execute the same template
The normal thing to do is to simply pass your template a struct with whatever static data you like. Unless I've misunderstood what you're trying to do, there doesn't seem to be any need for Funcs here. Simplifying your example:
package main
import (
"html/template"
"os"
)
const hometmpl = `
{{if .IsAdmin}}
Go to the big red nuclear button
{{end}}
`
var t = template.Must(template.New("home").Parse(hometmpl))
func isAdmin(token string) bool {
const adminToken = "0xCAFEBABE"
return token == adminToken
}
func main() {
token := "0xCAFEBABE" // Or extracted from the http.Request
t.ExecuteTemplate(os.Stdout, "home", struct{IsAdmin bool}{isAdmin(token)})
}

Mockito - Invalid use of argument matchers

I have Junit test that is testing jms message sending. I am using Spring jmsTemplate to to do this. Here I as in the following code I want to check whether the JMS template has called send message regardless what is it in the values of actuall parameters that are passed.
my publisher method the uses the jmsTemplate to send method looks like following inside..
jmsTemplate.send(jmsQueueProperties.getProperty(key), new MessageCreator()
{
public Message createMessage(Session session) throws JMSException
{
ObjectMessage obj = session.createObjectMessage(dialogueServiceResponse);
return obj;
}
});
in My tests..
JmsTemplate mockTemplate = Mockito.mock(JmsTemplate.class);
...
publisher.publishServiceMessage(response);
....
Mockito.verify(mockTemplate,
Mockito.times(1)).send("appointment.queue",
Mockito.any(MessageCreator.class));
But when in the execution i get
org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Invalid use of argument matchers!
....
Cause is due to Mockito.any(MessageCreator.class) , but isn't there a way to test my send method is getting executed without creating an actual object in the MessageCreator.
Update
And is there a way to check my session.createObjectMessage(dialogueServiceResponse) is getting called as well
I think the rest of the message tells you what the problem is. When you use an argument matcher for one of the arguments, all the other arguments must also use an argument matcher:
Mockito.verify(mockTemplate, Mockito.times(1)).send(
Mockito.eq("appointment.queue"),
Mockito.any(MessageCreator.class));
For future readers. This will save you a lot of time.
We cannot use argument matcher and primitive/raw values together.
when(fooService.getResult("string",any(MyClass.class))).thenReturn(1); // will give error
when(fooService.getResult(anyString(),any(MyClass.class))).thenReturn(1); // correct
I think you cannot use argument matchers outside stubbing. I also got the same error but when I return, I had to do new string() instead of Mockito.anyString() and the error goes away.
Example:
Mockito.when(mockedBean.mockedMethod(Mockito.anyString(),
Mockito.anyInt(),
Mockito.anyInt(),
Mockito.anyInt(),
Mockito.anyBoolean())).thenReturn(new String());
I can see that this question is about Java code, but I will share this because we use Mockito in Scala as well.
I had this exception thrown from the following code that mocks Play.api configurations
"Configurations Service" should {
"return all dataset configurations" in {
val configs = mock[Configuration]
val testData = Seq("SOME VALUE")
val loader = any[ConfigLoader[Seq[String]]]
when(configs.get[Seq[String]](any[String])).thenReturn(testData) // EXCEPTIONN HERE !
val configuration: ConfigurationsService = new ConfigurationsService(configs)
assert(configuration.getSupportedDatasets() == testData)
}
}
In Scala methods can have Implicit parameters configs.get method has one explicit param and an Implicit one I passed a mock object and when an exception was thrown I was wondering what is going on as I didn't MIX params and mocks, it turned out that I had to pass mocks to implicit parameters as well, and this solved the problem.
val loader = any[ConfigLoader[Seq[String]]] // configs.get has one implicit parameter that accepts ConfigLoader[Seq[String]]
when(configs.get[Seq[String]](any[String])(loader)).thenReturn(testData)
I was seeing this error about a mismatched # of arguments, despite having the correct number...
I realized this was because method being stubbed was static. When I converted it to non-static, it worked as expected.