void SG_dagfrag_debug__dump(SG_context * pCtx, SG_dagfrag * pFrag, const char * szLabel, SG_uint32 indent, SG_string * pStringOutput) { char buf[4000]; struct _dump_data dump_data; dump_data.indent = indent+4; dump_data.nrDigits = 6; dump_data.pStringOutput = pStringOutput; SG_ERR_CHECK_RETURN( SG_sprintf(pCtx, buf,SG_NrElements(buf),"%*cDagFrag[%p] [%s]\n",indent,' ',pFrag,szLabel) ); SG_ERR_CHECK_RETURN( SG_string__append__sz(pCtx, pStringOutput,buf) ); dump_data.stateWanted = SG_DFS_START_MEMBER; SG_ERR_CHECK_RETURN( SG_sprintf(pCtx, buf,SG_NrElements(buf),"%*cStartMembers:\n",indent+2,' ') ); SG_ERR_CHECK_RETURN( SG_string__append__sz(pCtx, pStringOutput,buf) ); SG_ERR_CHECK_RETURN( SG_rbtree__foreach(pCtx, pFrag->m_pRB_Cache,_dump_cb,&dump_data) ); dump_data.stateWanted = SG_DFS_INTERIOR_MEMBER; SG_ERR_CHECK_RETURN( SG_sprintf(pCtx,buf,SG_NrElements(buf),"%*cInteriorMembers:\n",indent+2,' ') ); SG_ERR_CHECK_RETURN( SG_string__append__sz(pCtx,pStringOutput,buf) ); SG_ERR_CHECK_RETURN( SG_rbtree__foreach(pCtx,pFrag->m_pRB_Cache,_dump_cb,&dump_data) ); dump_data.stateWanted = SG_DFS_END_FRINGE; SG_ERR_CHECK_RETURN( SG_sprintf(pCtx,buf,SG_NrElements(buf),"%*cEndFringe:\n",indent+2,' ') ); SG_ERR_CHECK_RETURN( SG_string__append__sz(pCtx,pStringOutput,buf) ); SG_ERR_CHECK_RETURN( SG_rbtree__foreach(pCtx,pFrag->m_pRB_Cache,_dump_cb,&dump_data) ); }
// Generates a vector from gaTestItems. void MyFn(_create_test_vector)( SG_context* pCtx, SG_vector** ppVector, SG_uint32* pSize ) { SG_vector* pVector = NULL; SG_uint32 uIndex = 0u; SG_uint32 uExpectedTotal = 0u; SG_uint32 uPass = 0u; SG_uint32 uPassTotal = 1u; SG_uint32 uActualTotal = 0u; // check how many big the final vector will be for (uIndex = 0u; uIndex < SG_NrElements(gaTestItems); ++uIndex) { test_item* pTestItem = gaTestItems + uIndex; uExpectedTotal += pTestItem->uCount; } // allocate the vector VERIFY_ERR_CHECK( SG_VECTOR__ALLOC(pCtx, &pVector, uExpectedTotal) ); // add the items in passes rather than each item sequentially // this way values appended multiple times won't be sequential while (uPassTotal > 0u) { uPassTotal = 0u; for (uIndex = 0u; uIndex < SG_NrElements(gaTestItems); ++uIndex) { test_item* pTestItem = gaTestItems + uIndex; if (pTestItem->uCount > uPass) { VERIFY_ERR_CHECK( SG_vector__append(pCtx, pVector, (void*)pTestItem->szValue, NULL) ); uPassTotal += 1u; } } uActualTotal += uPassTotal; uPass += 1u; } VERIFY_ERR_CHECK( MyFn(_verify_size)(pCtx, pVector, uExpectedTotal) ); VERIFY_ERR_CHECK( MyFn(_verify_size)(pCtx, pVector, uActualTotal) ); // return the vector if (ppVector != NULL) { *ppVector = pVector; pVector = NULL; } if (pSize != NULL) { *pSize = uActualTotal; } fail: SG_VECTOR_NULLFREE(pCtx, pVector); }
SG_error SGHASH_get_nth_hash_method_name(SG_uint32 n, char * pBufResult, SG_uint32 lenBuf, SG_uint32 * pStrlenHashes) { if (n >= SG_NrElements( SGHASH_alg__list )) return SG_ERR_INDEXOUTOFRANGE; if (pBufResult) { SG_uint32 lenHashMethodName = strlen(SGHASH_alg__list[n]->pszHashMethod); if (lenBuf < (lenHashMethodName + 1)) return SG_ERR_INVALIDARG; #if defined(WINDOWS) memcpy_s(pBufResult, lenBuf, SGHASH_alg__list[n]->pszHashMethod, lenHashMethodName+1); #else memcpy(pBufResult, SGHASH_alg__list[n]->pszHashMethod, lenHashMethodName+1); #endif } if (pStrlenHashes) *pStrlenHashes = SGHASH_alg__list[n]->strlen_Hash; return SG_ERR_OK; }
void MyFn(remove__value)(SG_context* pCtx) { SG_vector* pVector = NULL; SG_uint32 uSize = 0u; SG_uint32 uIndex = 0u; // create a test vector VERIFY_ERR_CHECK( MyFn(_create_test_vector)(pCtx, &pVector, &uSize) ); // run through each item and remove it by value // verify that we remove the number of values expected // also verify that the resulting size is as expected for (uIndex = 0u; uIndex < SG_NrElements(gaTestItems); ++uIndex) { test_item* pTestItem = gaTestItems + uIndex; SG_uint32 uRemoved = 0u; VERIFY_ERR_CHECK( SG_vector__remove__value(pCtx, pVector, (void*)pTestItem->szValue, &uRemoved, NULL) ); VERIFYP_COND("Removed wrong number of items.", uRemoved == pTestItem->uCount, ("Value(%s) Expected(%u) Removed(%u)", pTestItem->szValue, pTestItem->uCount, uRemoved)); uSize -= uRemoved; VERIFY_ERR_CHECK( MyFn(_verify_size)(pCtx, pVector, uSize) ); } fail: SG_VECTOR_NULLFREE(pCtx, pVector); return; }
void MyFn(create_zero_byte_blob)(SG_context* pCtx, SG_repo* pRepo) { struct z { const char * pszHashMethod; const char * pszTrivialHash; }; struct z az[] = { { "SHA1/160", "da39a3ee5e6b4b0d3255bfef95601890afd80709" }, { "SHA2/256", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, { "SHA2/384", "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b" }, { "SHA2/512", "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" }, }; char* pszidHidBlob1 = NULL; char * pbuf1 = NULL; char * pbuf2 = NULL; SG_uint64 lenBuf2; SG_repo_tx_handle* pTx = NULL; SG_uint32 lenBuf1 = 0; char * pszHashMethod = NULL; SG_uint32 k, kLimit; pbuf1 = (char *)SG_calloc(1,lenBuf1+1); VERIFY_ERR_CHECK_DISCARD( SG_repo__begin_tx(pCtx, pRepo, &pTx) ); VERIFY_ERR_CHECK_DISCARD( SG_repo__store_blob_from_memory(pCtx, pRepo,pTx,NULL,SG_FALSE,(SG_byte *)pbuf1,lenBuf1,&pszidHidBlob1) ); VERIFY_ERR_CHECK_DISCARD( SG_repo__commit_tx(pCtx, pRepo, &pTx) ); INFOP("create_zero_byte_blob",("Created blob [%s]",(pszidHidBlob1))); ////////////////////////////////////////////////////////////////// // fetch blob into a new buffer and verify that it matches. VERIFY_ERR_CHECK_DISCARD( SG_repo__fetch_blob_into_memory(pCtx, pRepo,pszidHidBlob1,(SG_byte **)&pbuf2,&lenBuf2) ); VERIFY_COND("create_zero_byte_blob(fetch blob)",(lenBuf2 == (SG_uint64)lenBuf1)); VERIFY_COND("create_zero_byte_blob(memcmp)",(memcmp(pbuf1,pbuf2,lenBuf1)==0)); VERIFY_ERR_CHECK_DISCARD( SG_repo__get_hash_method(pCtx, pRepo, &pszHashMethod) ); kLimit = SG_NrElements(az); for (k=0; k<kLimit; k++) { if (strcmp(pszHashMethod,az[k].pszHashMethod) == 0) { // The empty blob should always have this hid VERIFY_COND("zero byte blob hid mismatch", strcmp(pszidHidBlob1, az[k].pszTrivialHash) == 0); } } ////////////////////////////////////////////////////////////////// // cleanup SG_NULLFREE(pCtx, pbuf1); SG_NULLFREE(pCtx, pbuf2); SG_NULLFREE(pCtx, pszidHidBlob1); SG_NULLFREE(pCtx, pszHashMethod); }
int u0020_utf8pathnames__testfilename(SG_string * pStringFilename) { // verify that file name matches what we expect. // // WE RELY ON THE FACT THAT EACH FILENAME IN THE ARRAY STARTS // WITH A DIFFERENT LETTER. const char * szFilename = SG_string__sz(pStringFilename); char c = szFilename[0]; if (c == '.') // "." and ".." return 1; if ((c >= 'A') && (c <= 'Z')) { _tableitem * pti; size_t tableindex = (c - 'A'); SG_bool bTestIsNFC, bTestIsNFD; SG_bool bMatchGiven, bMatchNFC, bMatchNFD; VERIFYP_COND_RETURN("u0020_utf8pathnames",(tableindex < SG_NrElements(table)),("unexpected file [%s]",szFilename)); pti = &table[tableindex ]; // verify that we didn't mess up when creating the test case. bTestIsNFC = (strcmp((char *)pti->pa8,(char *)pti->paNfc) == 0); bTestIsNFD = (strcmp((char *)pti->pa8,(char *)pti->paNfd) == 0); VERIFYP_COND("u0020_utf8pathnames",(bTestIsNFC || bTestIsNFD),("Is tableitem[%c] NFC or NFD?",c)); // see if the filename we got from the system matches what we gave. // if not, see if it matches the NFC() version or the NFD() version. bMatchGiven = (strcmp(szFilename,(char *)pti->pa8) == 0); bMatchNFC = (strcmp(szFilename,(char *)pti->paNfc) == 0); bMatchNFD = (strcmp(szFilename,(char *)pti->paNfd) == 0); INFOP("u0020_utf8pathnames",("tableitem[%c] NFC[%d] [NFC %s NFD] : MatchGiven[%d] MatchNFC[%d] MatchNFD[%d]", c, bTestIsNFC,((bTestIsNFC == bTestIsNFD) ? "==" : "!="), bMatchGiven,bMatchNFC,bMatchNFD)); // // TODO fix this test based upon what we know about the platform. // VERIFYP_COND("u0020_utf8pathnames",(strcmp(szFilename,(char *)pti->pa8)==0),("Received [%s] expected [%s]",szFilename,pti->pa8)); return 1; } VERIFYP_COND_RETURN("u0020_utf8pathnames",(0),("unexpected file [%s]",szFilename)); }
SG_error SGHASH_init(const char * pszHashMethod, SGHASH_handle ** ppHandle) { int kLimit = SG_NrElements( SGHASH_alg__list ); int k; if (!ppHandle) return SG_ERR_INVALIDARG; if (!pszHashMethod || !*pszHashMethod) return _do_init( &SGHASH_ALGORITHM__DEFAULT, ppHandle); for (k=0; k<kLimit; k++) if (strcmp(pszHashMethod, SGHASH_alg__list[k]->pszHashMethod) == 0) return _do_init( SGHASH_alg__list[k], ppHandle); return SG_ERR_UNKNOWN_HASH_METHOD; }
SG_error SGHASH_get_hash_length(const char * pszHashMethod, SG_uint32 * pStrlenHashes) { int kLimit = SG_NrElements( SGHASH_alg__list ); int k; if (!pStrlenHashes) return SG_ERR_INVALIDARG; for (k=0; k<kLimit; k++) { if (strcmp(pszHashMethod, SGHASH_alg__list[k]->pszHashMethod) == 0) { *pStrlenHashes = SGHASH_alg__list[k]->strlen_Hash; return SG_ERR_OK; } } return SG_ERR_UNKNOWN_HASH_METHOD; }
static void my_dump_id(SG_context * pCtx, const char* psz_hid, SG_uint32 nrDigits, SG_uint32 indent, SG_string * pStringOutput) { char buf[4000]; // we can abbreviate the full IDs. nrDigits = SG_MIN(nrDigits, SG_HID_MAX_BUFFER_LENGTH); nrDigits = SG_MAX(nrDigits, 4); // create: // Dagnode[addr]: <child_id> <gen> [<parent_id>...] SG_ERR_CHECK_RETURN( SG_sprintf(pCtx,buf,SG_NrElements(buf),"%*c ",indent,' ') ); SG_ERR_CHECK_RETURN( SG_string__append__sz(pCtx,pStringOutput,buf) ); SG_ERR_CHECK_RETURN( SG_string__append__buf_len(pCtx,pStringOutput,(SG_byte *)(psz_hid),nrDigits) ); SG_ERR_CHECK_RETURN( SG_string__append__sz(pCtx,pStringOutput,"\n") ); }
void sg_vv2__status__assert_in_work_queue(SG_context * pCtx, sg_vv2status * pST, sg_vv2status_od * pOD, SG_uint32 depthInQueue) { char buf[SG_GID_BUFFER_LENGTH + 20]; SG_bool bFound; sg_vv2status_od * pOD_test; SG_ERR_CHECK_RETURN( SG_sprintf(pCtx, buf,SG_NrElements(buf), "%08d.%s", depthInQueue,pOD->bufGidObject) ); SG_ERR_CHECK_RETURN( SG_rbtree__find(pCtx, pST->prbWorkQueue,buf,&bFound,(void **)&pOD_test) ); SG_ASSERT_RELEASE_RETURN2( (bFound), (pCtx, "Object [GID %s][depth %d] should have been in work-queue.", pOD->bufGidObject, depthInQueue) ); }
void sg_vv2__status__remove_from_work_queue(SG_context * pCtx, sg_vv2status * pST, sg_vv2status_od * pOD, SG_uint32 depthInQueue) { char buf[SG_GID_BUFFER_LENGTH + 20]; SG_ERR_CHECK_RETURN( SG_sprintf(pCtx, buf,SG_NrElements(buf), "%08d.%s", depthInQueue,pOD->bufGidObject) ); #if TRACE_VV2_STATUS SG_console(pCtx, SG_CS_STDERR, "TD_RMQUE [GID %s][minDepth %d] (short circuit)\n", pOD->bufGidObject,depthInQueue); SG_ERR_DISCARD; #endif SG_ERR_CHECK_RETURN( SG_rbtree__remove(pCtx,pST->prbWorkQueue,buf) ); }
void SG_jscore__check_module_dags(SG_context *pCtx, JSContext *cx, JSObject *glob, const char *reponame) { jsval args[2]; JSBool js_ok; jsval rval; JSString *pjs; jsval fo = JSVAL_VOID; if (gpJSCoreGlobalState->bSkipModules || (! gpJSCoreGlobalState->pPathToModules)) return; SG_ERR_CHECK( _sg_jscore__install_modules(pCtx, cx, glob, NULL) ); SG_JS_NULL_CHECK( (pjs = JS_NewStringCopyZ(cx, reponame)) ); args[0] = STRING_TO_JSVAL(pjs); SG_JS_NULL_CHECK( (pjs = JS_NewStringCopyZ(cx, SG_pathname__sz(gpJSCoreGlobalState->pPathToModules))) ); args[1] = STRING_TO_JSVAL(pjs); if (! JS_LookupProperty(cx, glob, "checkModuleDags", &fo)) { SG_ERR_CHECK_CURRENT; SG_ERR_THROW2(SG_ERR_JS, (pCtx, "lookup of checkModuleDags failed")); } if (!JSVAL_IS_VOID(fo)) { js_ok = JS_CallFunctionName(cx, glob, "checkModuleDags", SG_NrElements(args), args, &rval); SG_ERR_CHECK_CURRENT; if(!js_ok) SG_ERR_THROW2(SG_ERR_JS, (pCtx, "An error occurred initializing modules: call to JavaScript checkModuleDags() failed")); } fail: ; }
/** * create (depth,ObjectGID) key and add entry to work-queue. */ void sg_vv2__status__add_to_work_queue(SG_context * pCtx, sg_vv2status * pST, sg_vv2status_od * pOD) { char buf[SG_GID_BUFFER_LENGTH + 20]; SG_ERR_CHECK_RETURN( SG_sprintf(pCtx, buf,SG_NrElements(buf), "%08d.%s", pOD->minDepthInTree,pOD->bufGidObject) ); #if TRACE_VV2_STATUS SG_console(pCtx, SG_CS_STDERR, "TD_ADQUE [GID %s][minDepth %d] type[%d,%d] depth[%d,%d]\n", pOD->bufGidObject,pOD->minDepthInTree, (int)((pOD->apInst[SG_VV2__OD_NDX_ORIG]) ? (int)pOD->apInst[SG_VV2__OD_NDX_ORIG]->typeInst : -1), (int)((pOD->apInst[SG_VV2__OD_NDX_DEST]) ? (int)pOD->apInst[SG_VV2__OD_NDX_DEST]->typeInst : -1), ((pOD->apInst[SG_VV2__OD_NDX_ORIG]) ? pOD->apInst[SG_VV2__OD_NDX_ORIG]->depthInTree : -1), ((pOD->apInst[SG_VV2__OD_NDX_DEST]) ? pOD->apInst[SG_VV2__OD_NDX_DEST]->depthInTree : -1)); SG_ERR_DISCARD; #endif SG_ERR_CHECK_RETURN( SG_rbtree__add__with_assoc(pCtx,pST->prbWorkQueue,buf,pOD) ); }
/** * For MODIFIED or ADDED items we need to populate the right side * of the diff. * * See footnote 1 above for bIsTmp_right. * */ static void _get_right_side_details(SG_context * pCtx, sg_wc6diff__setup_data * pData, const SG_vhash * pvhItem, sg_wc_liveview_item * pLVI, SG_vhash * pvhDiffItem) { SG_string * pStringLabel_right = NULL; SG_pathname * pPathAbsolute_right = NULL; SG_vhash * pvhSubsection_right = NULL; // we do not own this const char * pszRepoPath_right; char bufDate[SG_TIME_FORMAT_LENGTH+1]; SG_bool bIsTmp_right; SG_fsobj_stat st_right; // get the repo-path for the right side *AS IT EXISTED IN THE RIGHT CSET*. SG_ERR_CHECK( SG_vhash__get__vhash(pCtx, pvhItem, pData->pszSubsectionRight, &pvhSubsection_right) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvhSubsection_right, "path", &pszRepoPath_right) ); SG_ERR_CHECK( sg_wc_liveview_item__get_proxy_file_path(pCtx, pLVI, pData->pWcTx, &pPathAbsolute_right, &bIsTmp_right) ); SG_ERR_CHECK( SG_fsobj__stat__pathname(pCtx, pPathAbsolute_right, &st_right) ); SG_ERR_CHECK( SG_time__format_utc__i64(pCtx, st_right.mtime_ms, bufDate, SG_NrElements(bufDate)) ); // the right label is "<right_repo_path> <datestamp>" SG_ERR_CHECK( SG_fsobj__stat__pathname(pCtx, pPathAbsolute_right, &st_right) ); SG_ERR_CHECK( sg_wc_diff_utils__make_label(pCtx, pszRepoPath_right, NULL, bufDate, &pStringLabel_right) ); // put the various fields that we need to use in the call to SG_difftool__run() // into the pvhDiffItem for later. SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "right_label", SG_string__sz(pStringLabel_right)) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "right_abs_path", SG_pathname__sz(pPathAbsolute_right)) ); SG_ERR_CHECK( SG_vhash__add__bool( pCtx, pvhDiffItem, "right_is_tmp", bIsTmp_right) ); fail: SG_PATHNAME_NULLFREE(pCtx, pPathAbsolute_right); SG_STRING_NULLFREE(pCtx, pStringLabel_right); }
int u0020_utf8pathnames__test(SG_context * pCtx) { SG_pathname * pPathnameTmpDir; int k, kLimit; // create a temporary directory. VERIFY_ERR_CHECK_RETURN( u0020_utf8pathnames__mkdir_tmp_dir(pCtx, &pPathnameTmpDir) ); INFOP("u0020_utf8pathnames",("Creating directory [%s]",SG_pathname__sz(pPathnameTmpDir))); // create a series of files in the temporary directory that have // various unicode characters in their names. kLimit = SG_NrElements(table); for (k=0; k<kLimit; k++) { _tableitem * pti = &table[k]; INFOP("u0020_utf8pathnames",("[%d] starts with [%c]",k,pti->pa8[0])); VERIFY_ERR_CHECK_DISCARD( u0020_utf8pathnames__create_file(pCtx,pPathnameTmpDir,pti) ); } // open the tmp dir for reading and read the filename of each file in it. // compare these with the version of the filename that we used to create // the file. VERIFY_ERR_CHECK_DISCARD( u0020_utf8pathnames__readdir(pCtx, pPathnameTmpDir) ); // clean up our mess VERIFY_ERR_CHECK_DISCARD( SG_fsobj__rmdir_recursive__pathname(pCtx, pPathnameTmpDir) ); SG_PATHNAME_NULLFREE(pCtx, pPathnameTmpDir); return 1; }
static void _sg_dagfrag__my_create_generation_sorted_member_cache_callback(SG_context * pCtx, const char * szKey, void * pAssocData, void * pVoidFrag) { // a standard SG_rbtree_foreach_callback. // // insert a parallel item in the SORTED CACHE for this item from the regular CACHE. // we only want items of type START_MEMBER and INTERIOR_MEMBER in our sorted cache. _my_data * pMyData = (_my_data *)pAssocData; SG_dagfrag * pFrag = (SG_dagfrag *)pVoidFrag; char bufSortKey[SG_HID_MAX_BUFFER_LENGTH + 20]; switch (pMyData->m_state) { default: //case SG_DFS_UNKNOWN: //case SG_DFS_END_FRINGE: return; case SG_DFS_START_MEMBER: case SG_DFS_INTERIOR_MEMBER: break; } // the sort key looks like <generation>.<hid> "%08lx.%s" SG_ERR_CHECK_RETURN( SG_sprintf(pCtx, bufSortKey,SG_NrElements(bufSortKey), "%08lx.%s", pMyData->m_genDagnode,szKey) ); SG_ERR_CHECK_RETURN( SG_rbtree__update__with_assoc(pCtx, pFrag->m_pRB_GenerationSortedMemberCache,bufSortKey,pMyData,NULL) ); }
void MyFn(match_value__append)(SG_context* pCtx) { SG_vector* pVector = NULL; SG_uint32 uSize = 0u; SG_uint32 uIndex = 0u; SG_vector* pTarget = NULL; // create a test vector VERIFY_ERR_CHECK( MyFn(_create_test_vector)(pCtx, &pVector, &uSize) ); // run through each test item and copy all indices with that value to another vector // verify that the other vector receives the correct number of items for (uIndex = 0u; uIndex < SG_NrElements(gaTestItems); ++uIndex) { test_item* pTestItem = gaTestItems + uIndex; // allocate a target vector VERIFY_ERR_CHECK( SG_VECTOR__ALLOC(pCtx, &pTarget, uSize) ); // find all values that match the current item // add them to the target vector VERIFY_ERR_CHECK( SG_vector__find__all(pCtx, pVector, SG_vector__predicate__match_value, (void*)pTestItem->szValue, SG_vector__callback__append, pTarget) ); // verify the size of the target vector VERIFY_ERR_CHECK( MyFn(_verify_size)(pCtx, pTarget, pTestItem->uCount) ); // free the target vector SG_VECTOR_NULLFREE(pCtx, pTarget); pTarget = NULL; } fail: SG_VECTOR_NULLFREE(pCtx, pVector); SG_VECTOR_NULLFREE(pCtx, pTarget); return; }
SG_error SG_context__err_stackframe_add(SG_context* pCtx, const char* szFilename, SG_uint32 linenum) { SG_error err = SG_ERR_OK; SG_uint32 len_needed; SG_uint32 len_avail; char buf[20]; SG_ASSERT( pCtx ); // SG_ASSERT( pCtx->level < SG_CONTEXT_MAX_ERROR_LEVELS ); if (pCtx->level > 0) // when in an error-on-error (level > 0), return SG_ERR_OK; // we don't add to the stack trace. SG_ASSERT( (szFilename && *szFilename) ); SG_ASSERT( (linenum) ); SG_ASSERT( (SG_IS_ERROR(pCtx->errValues[pCtx->level])) ); SG_ASSERT( (!pCtx->bStackTraceAtLimit) ); // do all of the formatting in an error-on-error level so that none of // the string manipulation trashes the current error context. // // ***DO NOT JUMP OUT OF THIS PUSH..POP BLOCK.*** SG_context__push_level(pCtx); { SG_uint32 lenFilename; SG_uint32 lenLineNr; SG_sprintf(pCtx, buf, sizeof(buf), "%d", linenum); lenLineNr = strlen(buf); lenFilename = strlen(szFilename); len_needed = lenFilename + lenLineNr + 3; // 3 == \t, :, and \n. // TODO should 5 be 6 to account for the NULL byte? // 5 == "\t...\n" len_avail = SG_NrElements(pCtx->szStackTrace) - pCtx->lenStackTrace - 5; if (len_needed > len_avail) { pCtx->bStackTraceAtLimit = SG_TRUE; memmove(&pCtx->szStackTrace[pCtx->lenStackTrace],"\t...\n",5); pCtx->lenStackTrace += 5; pCtx->szStackTrace[pCtx->lenStackTrace] = 0; } else { pCtx->szStackTrace[pCtx->lenStackTrace] = '\t'; pCtx->lenStackTrace++; memmove(&pCtx->szStackTrace[pCtx->lenStackTrace],szFilename,lenFilename); pCtx->lenStackTrace+=lenFilename; pCtx->szStackTrace[pCtx->lenStackTrace] = ':'; pCtx->lenStackTrace++; memmove(&pCtx->szStackTrace[pCtx->lenStackTrace],buf,lenLineNr); pCtx->lenStackTrace+=lenLineNr; pCtx->szStackTrace[pCtx->lenStackTrace] = '\n'; pCtx->lenStackTrace++; pCtx->szStackTrace[pCtx->lenStackTrace] = 0; } err = pCtx->errValues[pCtx->level]; // we return the error value from the formatting. } SG_context__pop_level(pCtx); return err; }
int u0040_unc__stat_dir(SG_context * pCtx, const char * szDir) { SG_pathname * pPathname = NULL; SG_pathname * pPathnameFile = NULL; SG_file * pf = NULL; SG_fsobj_stat fsobjStat; SG_bool bFileExists; SG_int_to_string_buffer bufSize; char bufDate[100]; SG_context__err_reset(pCtx); ////////////////////////////////////////////////////////////////// // stat the given directory. ////////////////////////////////////////////////////////////////// INFOP("u0040_unc",("Inspecting [%s]",szDir)); VERIFY_ERR_CHECK_RETURN( SG_PATHNAME__ALLOC__SZ(pCtx,&pPathname,szDir) ); VERIFY_ERR_CHECK( SG_fsobj__stat__pathname(pCtx,pPathname,&fsobjStat) ); VERIFY_COND("u0040_unc",(fsobjStat.type == SG_FSOBJ_TYPE__DIRECTORY)); // TODO should we verify length == 0 ? // TODO should we verify modtime ? SG_uint64_to_sz(fsobjStat.size, bufSize); VERIFY_ERR_CHECK_DISCARD( SG_time__format_utc__i64(pCtx,fsobjStat.mtime_ms,bufDate,SG_NrElements(bufDate)) ); INFOP("u0040_unc",("Result: [perms %04o][type %d][size %s][mtime %s]", fsobjStat.perms,fsobjStat.type, bufSize,bufDate)); ////////////////////////////////////////////////////////////////// // create a unique file in the directory and stat it. ////////////////////////////////////////////////////////////////// VERIFY_ERR_CHECK( unittest__alloc_unique_pathname(pCtx,szDir,&pPathnameFile) ); INFOP("u0040_unc",(" Creating file [%s]",SG_pathname__sz(pPathnameFile))); VERIFY_ERR_CHECK( SG_file__open__pathname(pCtx,pPathnameFile,SG_FILE_CREATE_NEW | SG_FILE_RDWR,0777,&pf) ); VERIFY_ERR_CHECK( SG_fsobj__stat__pathname(pCtx,pPathnameFile,&fsobjStat) ); VERIFY_COND("u0040_unc",(fsobjStat.type == SG_FSOBJ_TYPE__REGULAR)); VERIFY_COND("u0040_unc",(fsobjStat.size == 0)); VERIFY_COND("u0040_unc",(SG_fsobj__equivalent_perms(fsobjStat.perms,0777))); // TODO should we verify modtime ? SG_uint64_to_sz(fsobjStat.size, bufSize); VERIFY_ERR_CHECK_DISCARD( SG_time__format_utc__i64(pCtx,fsobjStat.mtime_ms,bufDate,SG_NrElements(bufDate)) ); INFOP("u0040_unc",(" Result: [perms %04o][type %d][size %s][mtime %s]", fsobjStat.perms,fsobjStat.type, bufSize,bufDate)); VERIFY_ERR_CHECK_DISCARD( SG_file__close(pCtx, &pf) ); // delete the file and stat it again VERIFY_ERR_CHECK_DISCARD( SG_fsobj__remove__pathname(pCtx,pPathnameFile) ); VERIFY_ERR_CHECK_DISCARD( SG_fsobj__exists__pathname(pCtx,pPathnameFile,&bFileExists,NULL,NULL) ); VERIFY_COND("u0040_unc",(!bFileExists)); ////////////////////////////////////////////////////////////////// // clean up ////////////////////////////////////////////////////////////////// SG_PATHNAME_NULLFREE(pCtx, pPathnameFile); SG_PATHNAME_NULLFREE(pCtx, pPathname); return 1; fail: SG_FILE_NULLCLOSE(pCtx, pf); SG_PATHNAME_NULLFREE(pCtx, pPathnameFile); SG_PATHNAME_NULLFREE(pCtx, pPathname); return 0; }
void MyFn(find)(SG_context* pCtx) { // the test data contains the same set of elements twice in the same order static const char* aData[] = { "abc", "123", "456", "def", "abc", "123", "456", "def", }; static const SG_uint32 uMiddle = SG_NrElements(aData) / 2u; SG_vector* pVector = NULL; SG_uint32 uIndex = 0u; SG_bool bFound = SG_FALSE; // create a vector containing our test data VERIFY_ERR_CHECK( SG_VECTOR__ALLOC(pCtx, &pVector, 5u) ); for (uIndex = 0u; uIndex < SG_NrElements(aData); ++uIndex) { SG_uint32 uAddIndex = 0u; VERIFY_ERR_CHECK( SG_vector__append(pCtx, pVector, (void*)aData[uIndex], &uAddIndex) ); VERIFY_COND("Test value added to wrong index.", uIndex == uAddIndex); } // make sure we find each of the values somewhere in the vector for (uIndex = 0u; uIndex < uMiddle; ++uIndex) { VERIFY_ERR_CHECK( SG_vector__contains(pCtx, pVector, (void*)aData[uIndex], &bFound) ); VERIFY_COND("Expected value not found.", bFound == SG_TRUE); } // look for a couple items we know aren't in the vector VERIFY_ERR_CHECK( SG_vector__contains(pCtx, pVector, NULL, &bFound) ); VERIFY_COND("Unexpected value found.", bFound == SG_FALSE); VERIFY_ERR_CHECK( SG_vector__contains(pCtx, pVector, (void*)pVector, &bFound) ); VERIFY_COND("Unexpected value found.", bFound == SG_FALSE); VERIFY_ERR_CHECK( SG_vector__contains(pCtx, pVector, (void*)&uIndex, &bFound) ); VERIFY_COND("Unexpected value found.", bFound == SG_FALSE); // make sure we find each of the values in their first location correctly for (uIndex = 0u; uIndex < uMiddle; ++uIndex) { SG_uint32 uFoundIndex = 0u; void* pFoundData = NULL; VERIFY_ERR_CHECK( SG_vector__find__first(pCtx, pVector, _match_string, (void*)aData[uIndex], &uFoundIndex, &pFoundData) ); VERIFY_COND("Value found at wrong index.", uIndex == uFoundIndex); VERIFY_COND("Wrong value found.", strcmp(aData[uIndex], (const char*)pFoundData) == 0); // make sure we don't crash if we don't want either output VERIFY_ERR_CHECK( SG_vector__find__first(pCtx, pVector, _match_string, (void*)aData[uIndex], NULL, NULL) ); } // make sure we find each of the values in their last location correctly for (uIndex = uMiddle; uIndex < SG_NrElements(aData); ++uIndex) { SG_uint32 uFoundIndex = 0u; void* pFoundData = NULL; VERIFY_ERR_CHECK( SG_vector__find__last(pCtx, pVector, _match_string, (void*)aData[uIndex], &uFoundIndex, &pFoundData) ); VERIFY_COND("Value found at wrong index.", uIndex == uFoundIndex); VERIFY_COND("Wrong value found.", strcmp(aData[uIndex], (const char*)pFoundData) == 0); // make sure we don't crash if we don't want either output VERIFY_ERR_CHECK( SG_vector__find__last(pCtx, pVector, _match_string, (void*)aData[uIndex], NULL, NULL) ); } // make sure we find each value at each of its locations correctly for (uIndex = 0u; uIndex < uMiddle; ++uIndex) { _verify_value_data cData; cData.szExpectedValue = aData[uIndex]; cData.uExpectedIndex = uIndex; cData.uMiddleIndex = uMiddle; VERIFY_ERR_CHECK( SG_vector__find__all(pCtx, pVector, _match_string, (void*)aData[uIndex], _verify_value, (void*)&cData) ); } fail: SG_VECTOR_NULLFREE(pCtx, pVector); }