-
2008年07月04日
Hard Link、Soft Link和Symbolic Link
Hard Links是文件系统展现一个文件通过不止一次引用在同一卷中的一个单独文件;junction(有被叫作soft link) 能连接位于同一计算机上不同本地卷的目录;Symbolic Links是一个文件系统对象指向另一个文件系统对象,它被设计来辅助迁移和同UNIX操作系统的应用程序兼容性,它从Windows Vista上的NTFS开始可用。
Demystifying the WinSxS directory in Windows-解释了Hard Links导致Windows文件夹过大问题,NTFS Misreports Free Space?提供了可用空间计算不一致的诊断方法。
-
2008年06月30日
本月文章收录
Mascara-ECMAScript 4转换经典 JavaScript工具
OpenJDK-Sun的开源Java实现
The Best Developer Cheat Sheets Around
Firefox 3 Memory Benchmarks and Comparison
Windows Server 2008和Vista SP1新特性Windows Error Reporting (WER)-LocalDumps
-
2008年06月17日
Unix/Linux速查表
Linux Commands - A practical reference
Linux-Unix cheat sheets - The ultimate collection
Unix Toolbox - a collection of Unix/Linux/BSD commands and tasks
Advanced Bash-Scripting Guide- An in-depth exploration of the art of shell scripting
Linux BASH command line
-
2008年06月15日
【翻译】如何测试AJAX应用程序
原作者:Markus Clermont, John Thomas
原文第一部分
背景
通常我们解决测试AJAX应用程序通过过多的大的端到端测试,并且(很有希望地)高单元测试覆盖。这里,我们概要了用这种方法的主要问题并演示一个有效的测试策略为一个基于GWT应用程序的示例,它超过“测试仅通过GUI。”
纯GUI测试的问题
一般通过GUI测试:
l 是昂贵的(需要长时间写测试而且执行是资源密集型)
l 有限地深入系统
l 通常仅考虑“恰当路径”
l 把多个方面化合成单个测试
l 速度慢且脆弱
l 需要大量的维护
l 很难调试
而在单元测试中不面临许多这些问题,它们本身不够主要是因为它们:
l 较少深入组件间如何相互交互
l 不提供业务逻辑和系统功能满足需求的信心
解决办法
虽然没有“一个通适”解决方案,有一些基本原则我们可以使用,以解决web应用程序的测试问题:
l 投资在集成测试(找出最小的子系统)
l 关注分离(不做安排通过你正在测试的接口)
l 单独地测试每个接口(模拟出所有你不在测试的内容)
l 考虑在生产中的依赖 (找出如何依赖能失败,并测试它)
l 混合使用策略和工具。没有银弹。
l 还有不要。。。你不能扔弃你所有的端到端测试
好的测试食谱
使用上述原则我们可以建立用于测试 Web 应用程序一个食谱。
1. 探索系统的功能
2. 确定系统的体系结构
3. 确定组件间的接口
4. 确定的依存关系和故障状态
5. 对每个功能:
l 确定参加组件
l 找出潜在的问题
l 隔离测试问题
l 创造一个“恰当路径”测试
后注:测试的价值
常见由开发人员编写测试时问道的问题,“这真正值得我的时间?”简短的回答是“总是!”。由于修复一个bug比首先预防它更为昂贵,编写好的测试始终值得耗费时间。
虽然有许多不同分类的测试,最常见分类它们的方式是基于它们的大小和它们测试产品的面。每个测试回答有关产品的特定的问题:
l 单元测试:该方法履行了其制约?
l 小集成测试:两个类能互相交互?
l 中等集成测试:类能正确交互它的依赖?是否正确预见和处理错误?所需的函数是否公开API或GUI 上?
l 子系统测试:两个子系统能互相交互?是否其中一个预期其它所有的错误并相应地处理它们?
l 系统测试:是否整个系统如预期表现?
记住这个问题,各种级别的测试使我们可以编写更集中和有意义的测试。请记住有效的测试是指那些提供快速和有用的反馈,即快速识别问题和定位该问题的确切位置。
-
2008年06月12日
PreCreateWindow
MFC9.0中
wincore.cpp中实现的函数AfxEndDeferRegisterClass自动预注册3个窗口类,分别为_afxWnd,_afxWndOleControl和_afxWndControlBar。自MFC 4.0起,类AfxWnd, AfxFrameOrView, AfxMDIFrame和AfxControlBar不再预注册,见KB 140596。
BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)
{
...
// work to register classes as specified by fToRegister, populate fRegisteredClasses as we go
if (fToRegister & AFX_WND_REG)
{
// Child windows - no brush, no icon, safest default class styles
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpszClassName = _afxWnd;
if (AfxRegisterClass(&wndcls))
fRegisteredClasses |= AFX_WND_REG;
}
if (fToRegister & AFX_WNDOLECONTROL_REG)
{
// OLE Control windows - use parent DC for speed
wndcls.style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpszClassName = _afxWndOleControl;
if (AfxRegisterClass(&wndcls))
fRegisteredClasses |= AFX_WNDOLECONTROL_REG;
}
if (fToRegister & AFX_WNDCONTROLBAR_REG)
{
// Control bar windows
wndcls.style = 0; // control bars don't handle double click
wndcls.lpszClassName = _afxWndControlBar;
wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
if (AfxRegisterClass(&wndcls))
fRegisteredClasses |= AFX_WNDCONTROLBAR_REG;
}
if (fToRegister & AFX_WNDMDIFRAME_REG)
{
// MDI Frame window (also used for splitter window)
wndcls.style = CS_DBLCLKS;
wndcls.hbrBackground = NULL;
if (_AfxRegisterWithIcon(&wndcls, _afxWndMDIFrame, AFX_IDI_STD_MDIFRAME))
fRegisteredClasses |= AFX_WNDMDIFRAME_REG;
}
if (fToRegister & AFX_WNDFRAMEORVIEW_REG)
{
// SDI Frame or MDI Child windows or views - normal colors
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))
fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;
}
if (fToRegister & AFX_WNDCOMMCTLS_REG)
{
// this flag is compatible with the old InitCommonControls() API
init.dwICC = ICC_WIN95_CLASSES;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WIN95CTLS_MASK);
fToRegister &= ~AFX_WIN95CTLS_MASK;
}
if (fToRegister & AFX_WNDCOMMCTL_UPDOWN_REG)
{
init.dwICC = ICC_UPDOWN_CLASS;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_UPDOWN_REG);
}
…
if (fToRegister & AFX_WNDCOMMCTL_PAGER_REG)
{
init.dwICC = ICC_PAGESCROLLER_CLASS;
fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_PAGER_REG);
}
...
}
之后进入AfxDeferRegisterClass,再进入实现在MainFrm.cpp中(这是由于CMainFrame中重写了PreCreateWindow)的函数CMainFrame::PreCreateWindow中
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) ① )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return TRUE;
}
①处调用winfrm.cpp中的函数PreCreateWindow
BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
if (cs.lpszClass == NULL)
{
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background
}
if (cs.style & FWS_ADDTOTITLE)
cs.style |= FWS_PREFIXTITLE;
cs.dwExStyle |= WS_EX_CLIENTEDGE;
return TRUE;
}
其中函数AfxDeferRegisterClass定义在afximpl.h中
#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)
以上完成了注册窗口过程。
再转入实现在winfrm.cpp中的函数CFrameWnd::Create
BOOL CFrameWnd::Create(LPCTSTR lpszClassName,
LPCTSTR lpszWindowName,
DWORD dwStyle,
const RECT& rect,
CWnd* pParentWnd,
LPCTSTR lpszMenuName,
DWORD dwExStyle,
CCreateContext* pContext)
{
HMENU hMenu = NULL;
if (lpszMenuName != NULL)
{
// load in a menu that will get destroyed when window gets destroyed
…
if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext))
{…}
return TRUE;
}
它调用了实现在wincore.cpp中的函数CWnd::CreateEx创建窗口
BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle,
int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
{
…
if (!PreCreateWindow(cs) ②)
{
PostNcDestroy();
return FALSE;
}
AfxHookWindowCreate(this);
…
}
②处为函数CMainFrame::PreCreateWindow。
综上流程,CMainFrame::PreCreateWindow分别在注册和创建窗口时被2次调用。搜寻MFC调用顺序可以调试(Debug)应用程序,把Step Into(F11),Step Over(F10)和断点(Breakpoint)结合使用,效果最佳!
由于定义在afxwin.h中的函数是虚函数
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
因而可以在自己程序定义的CMainFrame中重写(Override)它,在该函数的第一行加入调试(Debug)中的事件纪录,TRACE/TRACE0/TRACE1/TRACE2/TRACE3,非MFC程序则需要用Win32格式化调试输出。
TRACE(L"CMainFrame::PreCreateWindow \n");
这样就能在调试(Debug)中看到此输出(output)信息,可以看到它输出了两次,这从另一方面再次验证了上述结论,由于C++多态性,派生类中重写虚函数,若对象是派生类则调用派生类的函数。若再在程序的View类(如类CxxxView,xxx为项目名)中重写此方法,在该函数的第一行加上
可以看到,此输出接在CMainFrame的两次输出后仅输出一次。TRACE(L"CtestView::PreCreateWindow \n");
最后,类CFormView和CRecordView不调用函数PreCreateWindow,见KB 131989。












