C/C++ log工具类LogUtils

一、前言

开发中打印一些程序 log 是一个很很很常用的需求了,怎么样打印这些 log 其实也很重要,除了必须的一些信息外,通常打印出这条 log 信息所在的 文件名方法行号 这类通用信息,也可以更好的帮助我们定位问题。并且,C 语言的 printf 为例,它并不是自己换行,每行 log 还需要我们手动添加一个 \n ,这个也是比较麻烦的,还容易漏掉。

所以,我们可以定制一个这样的 log 输出工具,输出一些通用信息(例如文件名、方法名、行号等),同时还可以添加一个统一的 log 开关,达成一次性关掉所有 log 的功能。

二、LogUtils 实例

这里以 C 语言为例,写了一个 LogUtils.h 文件,其它 C++、Android NDK 等类似语言,都可以在此基础上稍加修改即可。

LogUtils.h:

#ifndef _LOG_UTILS_H_
#define _LOG_UTILS_H_
 
#include <stdio.h>
#include <string.h>
 
#define DEBUG // log开关
 
#define __FILENAME__ (strrchr(__FILE__, '/') + 1) // 文件名
 
#ifdef DEBUG
#define LOGD(format, ...) printf("[%s][%s][%d]: " format "\n", __FILENAME__, __FUNCTION__,\
                            __LINE__, ##__VA_ARGS__)
#else
#define LOGD(format, ...)
#endif
 
#endif // _LOG_UTILS_H_

编写一个小程序测试一下:

#include <stdio.h>
#include "LogUtils.h"

int main() {
    LOGD("hello world");
    LOGD("%d", 10);
    LOGD("%s : %d", "num", 20);
    LOGD();
    return 0;
}

执行结果:

[main.cpp][main][5]: hello world
[main.cpp][main][6]: 10
[main.cpp][main][7]: num : 20
[main.cpp][main][8]: 

可以看到,输出的 log 已经是按照我们预设的那样,打印出了 文件名方法行号 这类通用信息,且实现的每行 log 自动换行。

注意:

如果需要关掉所有的 log,只需要注释掉 #define DEBUG 即可。也可以通过直接在 gcc 命令中添加 -DDEBUG 定义这个宏。

三、通用的一些宏定义解释

上面的代码中用到了一些系统提供的宏定义,这里简单的介绍一下它们的含义:

  • __FILE__ : 当前文件路径,注意这个是文件路径,如果我们只希望得到文件名,那么像我上面的示例中那样处理一下即可
  • __FUNCTION__ : 函数名,即输出这条宏命令所在的函数的名字
  • __LINE__ : 行号,即输出这条宏命令所在文件的第几行
  • __VA_ARGS__ : 可变变量,即将方法中的 "..." 替换到 __VA_ARGS__ 处,前面加上 "##" 是为了适应前面一个逗号,避免 "..." 为空时出错。

值得注意的是,宏定义都是在预编译时期就会替换到相应代码中去的。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你可以使用JUnit来测试这个方法。首先,需要准备好测试所需的对象和依赖项:NotificationChannel,NotificationManager,NotificationCompat.Builder和Notification。这些对象可以使用Mockito框架进行模拟。然后,你可以使用@Before注释来准备测试环境,在测试时调用makeForeground()方法,并使用Mockito.verify()方法来验证方法是否按预期工作。下面是一个可能的测试示例: ``` import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import android.graphics.Color; import androidx.core.app.NotificationCompat; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; public class MyServiceTest { private MyService myService; @Mock private NotificationManager notificationManager; @Mock private NotificationCompat.Builder notificationBuilder; @Mock private Notification notification; @Before public void setUp() { MockitoAnnotations.initMocks(this); myService = new MyService(); Mockito.when(myService.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(notificationManager); Mockito.when(notificationBuilder.setOngoing(true)).thenReturn(notificationBuilder); Mockito.when(notificationBuilder.setSmallIcon(Mockito.anyInt())).thenReturn(notificationBuilder); Mockito.when(notificationBuilder.setContentTitle(Mockito.anyString())).thenReturn(notificationBuilder); Mockito.when(notificationBuilder.setPriority(Mockito.anyInt())).thenReturn(notificationBuilder); Mockito.when(notificationBuilder.setCategory(Mockito.anyString())).thenReturn(notificationBuilder); Mockito.when(notificationBuilder.build()).thenReturn(notification); } @Test public void testMakeForeground() { // Call the method under test myService.makeForeground(); // Verify that the correct NotificationChannel was created Mockito.verify(notificationManager).createNotificationChannel(Mockito.argThat(channel -> { return channel.getId().equals(MyService.TAG) && channel.getName().equals(MyService.TAG) && channel.getImportance() == NotificationManager.IMPORTANCE_NONE && channel.getLightColor() == Color.BLUE && channel.getLockscreenVisibility() == Notification.VISIBILITY_PRIVATE; })); // Verify that the correct Notification was built and started Mockito.verify(notificationManager).startForeground(2, notification); } } ``` 在这个测试中,我们使用了@Mock注释来创建模拟对象,并使用Mockito.when()方法来设置它们的行为。在setUp()方法中,我们还模拟了MyService.getSystemService()方法的返回值,以便可以使用模拟的NotificationManager对象。在testMakeForeground()方法中,我们调用makeForeground()方法,并使用Mockito.verify()方法来验证预期行为。首先,我们验证正确的NotificationChannel是否被创建,然后验证正确的Notification是否被构建并启动。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值