您当前的位置:首页 > IT编程 > C++
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch | 异常检测 | Transformers | 情感分类 | 知识图谱 |

自学教程:C++ CuAssert函数代码示例

51自学网 2021-06-01 20:15:45
  C++
这篇教程C++ CuAssert函数代码示例写得很实用,希望能帮到您。

本文整理汇总了C++中CuAssert函数的典型用法代码示例。如果您正苦于以下问题:C++ CuAssert函数的具体用法?C++ CuAssert怎么用?C++ CuAssert使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。

在下文中一共展示了CuAssert函数的30个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的C++代码示例。

示例1: testRecvFail

static void testRecvFail(CuTest *tc) {	NTPSock*listenSock;	NTPSock*connectSock;	NTPSock*acceptSock;	char buf[20];	int result;	uint16_t port = 38712;	//connect the sockets	connectUtil(tc, &listenSock, &connectSock, &acceptSock, port);		//close one socket	NTPDisconnect(&connectSock);	CuAssert(tc, "disconnect to NULL", connectSock==NULL);	//try to recv() on the other socket	result = NTPRecv(acceptSock, buf, sizeof(buf));	CuAssert(tc, "recv should fail", result<=0);	//cleanup	NTPDisconnect(&listenSock);	NTPDisconnect(&acceptSock);	CuAssert(tc, "disconnect NULL", listenSock==NULL);	CuAssert(tc, "disconnect NULL", acceptSock==NULL);}
开发者ID:phantomfive,项目名称:NOTRAP,代码行数:25,


示例2: TestSetThreadCount

int TestSetThreadCount(CuTest *ct) { /* SKIP *//* Run this test only when hash is supported. */#ifdef HAVE_HASH	DB_ENV *dbenv;	DB *db;	CuAssert(ct, "db_env_create", db_env_create(&dbenv, 0) == 0);	dbenv->set_errpfx(dbenv, "TestSetThreadCount");	CuAssert(ct, "set_thread_count", dbenv->set_thread_count(dbenv, 2) == 0);	CuAssert(ct, "env->open", dbenv->open(dbenv, ".",			DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL |			DB_INIT_TXN | DB_PRIVATE | DB_THREAD, 0) == 0);	CuAssert(ct, "db_create", db_create(&db, dbenv, 0) == 0);	CuAssert(ct, "DB->open", db->open(	    db, NULL, NULL, "TestSetThreadCount", DB_HASH, DB_CREATE, 0) == 0);	db->close(db, 0);	dbenv->close(dbenv, 0);#else	printf("TestSetThreadCount is not supported by the build./n");#endif /* HAVE_HASH */	return (0);}
开发者ID:Pakrik,项目名称:libdb,代码行数:25,


示例3: t_file___write_block

/* * To verify the integrity of the output file produced * I hand walked through the complete file ensuring that * it held to the file schema--Bill */void t_file___write_block(CuTest *tc) {	FILE *fp, *f;	m_uword cnt;	m_uword tmp;	int i, j;	m_file_block block;	miniat *m;	m = malloc(sizeof(miniat));	fp = fopen("write_block.miniat", "w+");	CuAssert(tc, "File pointer not equal to NULL", fp != NULL);	/*write the header*/	cnt = (rand() % 20) + 10;	m_file_write_block_count (m, fp, cnt);	/*start building the body data to write*/	for(i=0; i<cnt; i++) {		block.number = i;		block.id = (rand() % m_block_type_cnt);		block.start_address = ((rand() << 16) | (rand()));		block.length = rand()%32;		block.data = (m_uword *)malloc(sizeof(m_uword) * block.length);		CuAssert(tc, "Block data not equal to NULL", block.data != NULL);		/*make some data*/		for(j=0; j < block.length; j++) {			block.data[j] = ((rand() << 16) | (rand()));		}		/*write the block*/		m_file_write_block (m, fp, &block);		/*free the block.data*/		if(block.data) {			for(j=0; j < block.length; j++) {				//free(block.data[j]);			}			//free(block.data);			block.data = NULL;		}	}	/*rewind the file pointer and read the blocks to verify*/	rewind(fp);	/*check the counts*/	m_file_read_block_count (m, fp, &tmp);	CuAssert(tc, "Block count matches previous block count", cnt == tmp);	if(fp) {		fclose(fp);	}	if(m) {		free(m);	}	remove("write_block.miniat");	return;}
开发者ID:L-u-k-e,项目名称:MiniAT,代码行数:65,


示例4: testSendFail

static void testSendFail(CuTest *tc) {	NTPSock *listenSock;	NTPSock *connectSock;	NTPSock *acceptSock;	char buf[] = "So remember, remember the Red River Valley";	int result;	uint16_t port = 23551;	//connect the sockets	connectUtil(tc, &listenSock, &connectSock, &acceptSock, port);	//close one socket	NTPDisconnect(&acceptSock);	CuAssert(tc, "disconnect to NULL", acceptSock==NULL);	//try to send() on the other socket. Keep trying	//because it doesn't always fail the first time.	int i;	for(i=0;i<20;i++) {		result = NTPSend(connectSock, buf, NTPstrlen(buf));	}	CuAssert(tc, "Send should fail", result<=0);	//cleanup	NTPDisconnect(&listenSock);	NTPDisconnect(&connectSock);	CuAssert(tc, "disconnect NULL", listenSock==NULL);	CuAssert(tc, "disconnect NULL", acceptSock==NULL);}
开发者ID:phantomfive,项目名称:NOTRAP,代码行数:29,


示例5: testSerializePublicationsFile

static void testSerializePublicationsFile(CuTest *tc) {	int res;	KSI_PublicationsFile *pubFile = NULL;	char *raw = NULL;	unsigned raw_len = 0;	FILE *f = NULL;	int symbol = 0;	unsigned i= 0;		KSI_ERR_clearErrors(ctx);	setFileMockResponse(tc, getFullResourcePath(TEST_PUBLICATIONS_FILE));	res = KSI_PublicationsFile_fromFile(ctx, getFullResourcePath(TEST_PUBLICATIONS_FILE), &pubFile);	CuAssert(tc, "Unable to read publications file", res == KSI_OK && pubFile != NULL);	res = KSI_PublicationsFile_serialize(ctx, pubFile, &raw, &raw_len);	CuAssert(tc, "Unable to serialize publications file", res == KSI_OK && raw != NULL && raw_len != 0);		f = fopen(getFullResourcePath(TEST_PUBLICATIONS_FILE), "rb");	CuAssert(tc, "Unable to open publications file", res == KSI_OK && f != NULL);		while ((symbol = getc(f)) != EOF && i<raw_len){		CuAssert(tc, "Serialized publications file mismatch", (char)symbol == raw[i]);		i++;	}		CuAssert(tc, "Serialized publications file length  mismatch", i == raw_len);		KSI_PublicationsFile_free(pubFile);	KSI_free(raw);	if (f) fclose(f);}
开发者ID:khushil,项目名称:libksi,代码行数:33,


示例6: expect_authentic

static voidexpect_authentic (CuTest *tc,                  const int expected_status,                  SignedVotedBallot const svbs,                  VoterRoll const vr,                  BlankBallot const bb){   char *raw_ballot_box = 0;   CuAssert (tc,             (0 == expected_status ?              "VHTI_authenticate should have accepted valid input"              : "VHTI_authenticate should have rejected invalid input"),             expected_status == VHTI_authenticate (svbs, vr, bb, &raw_ballot_box));   if (0 != expected_status)   {      if (raw_ballot_box)         fprintf (stderr, "Hmm: `%s'/n", raw_ballot_box);      CuAssertPtrEquals (tc, NULL, raw_ballot_box);   }   else   {      CuAssertPtrNotNull (tc, raw_ballot_box);      CuAssert (tc,                "VHTI_authenticate should have returned a RawBallotBox",                0 == VHTI_validate (RAW_BALLOT_BOX, raw_ballot_box));      VHTI_free (raw_ballot_box);   }}
开发者ID:darg0001,项目名称:evoting-systems,代码行数:30,


示例7: testVerifySignatureWithUserPublication

static void testVerifySignatureWithUserPublication(CuTest *tc) {	int res;	KSI_Signature *sig = NULL;	const char pubStr[] = "AAAAAA-CTOQBY-AAMJYH-XZPM6T-UO6U6V-2WJMHQ-EJMVXR-JEAGID-2OY7P5-XFFKYI-QIF2LG-YOV7SO";	const char pubStr_bad[] = "AAAAAA-CT5VGY-AAPUCF-L3EKCC-NRSX56-AXIDFL-VZJQK4-WDCPOE-3KIWGB-XGPPM3-O5BIMW-REOVR4";	KSI_PublicationData *pubData = NULL;	KSI_PublicationData *pubData_bad = NULL;	KSI_ERR_clearErrors(ctx);	res = KSI_PublicationData_fromBase32(ctx, pubStr, &pubData);	CuAssert(tc, "Unable to parse publication string.", res == KSI_OK && pubData != NULL);	res = KSI_PublicationData_fromBase32(ctx, pubStr_bad, &pubData_bad);	CuAssert(tc, "Unable to parse publication string.", res == KSI_OK && pubData_bad != NULL);	res = KSI_Signature_fromFile(ctx, getFullResourcePath("resource/tlv/ok-sig-2014-04-30.1-extended.ksig"), &sig);	CuAssert(tc, "Unable to read signature from file.", res == KSI_OK && sig != NULL);	res = KSI_Signature_verifyWithPublication(sig, ctx, pubData);	CuAssert(tc, "Unable to verify signature with publication.", res == KSI_OK);	res = KSI_Signature_verifyWithPublication(sig, ctx, pubData_bad);	CuAssert(tc, "Unable to verify signature with publication.", res != KSI_OK);	KSI_PublicationData_free(pubData);	KSI_PublicationData_free(pubData_bad);	KSI_Signature_free(sig);}
开发者ID:khushil,项目名称:libksi,代码行数:32,


示例8: TestSessionKeyTableAPI

void TestSessionKeyTableAPI( CuTest* tc ){	dssl_SessionKeyTable* tbl = NULL;	DSSL_Session* sess = NULL;	DSSL_SessionKeyData* kd = NULL;	tbl = dssl_SessionKT_Create( 100, TEST_CACHE_TIMEOUT );	CuAssert( tc, "SessionKeyTable object should be not NULL", tbl != NULL );	sess = (DSSL_Session*) malloc( sizeof( DSSL_Session ) );	CuAssert( tc, "DSSL_Session object should be not NULL", sess != NULL );		memset( sess, 0, sizeof(*sess) );	dssl_SessionKT_Add( tbl, sess );	CuAssertTrue( tc, tbl->count == 1 );	kd = dssl_SessionKT_Find( tbl, sess->session_id );	CuAssertTrue( tc, kd != NULL );	CuAssertTrue( tc, kd->refcount == 1 );	CuAssertTrue( tc, kd->released_time == 0 );	kd = NULL; 	dssl_SessionKT_Release( tbl, sess->session_id );	ThreadSleep( (TEST_CACHE_TIMEOUT+1)*1000 );	dssl_SessionKT_CleanSessionCache( tbl );	CuAssertTrue( tc, tbl->count == 0 );	free( sess );	dssl_SessionKT_Destroy( tbl );}
开发者ID:Correlsense,项目名称:libdssl,代码行数:34,


示例9: testExtractingNotExisting

static void testExtractingNotExisting(CuTest* tc) {	int res;	KSI_Signature *sig = NULL;	KSI_MultiSignature *ms = NULL;	KSI_DataHash *hsh = NULL;	KSI_ERR_clearErrors(ctx);	res = KSI_Signature_fromFile(ctx, getFullResourcePath(TEST_SIGNATURE_FILE), &sig);	CuAssert(tc, "Unable to read signature from file.", res == KSI_OK && sig != NULL);	res = KSI_MultiSignature_new(ctx, &ms);	CuAssert(tc, "Unable to create multi signature container.", res == KSI_OK && ms != NULL);	res = KSI_MultiSignature_add(ms, sig);	CuAssert(tc, "Unable to add signature to multi signature container.", res == KSI_OK);	KSI_Signature_free(sig);	sig = NULL;	KSITest_DataHash_fromStr(ctx, "01db27c0db0aebb8d3963c3a720985cedb600f91854cdb1e45ad631611c39284dd", &hsh);	res = KSI_MultiSignature_get(ms, hsh, &sig);	CuAssert(tc, "Get should fail with KSI_MULTISIG_NOT_FOUND", res == KSI_MULTISIG_NOT_FOUND && sig == NULL);	KSI_DataHash_free(hsh);	KSI_MultiSignature_free(ms);	KSI_Signature_free(sig);}
开发者ID:GuardTime,项目名称:libksi,代码行数:30,


示例10: testVerifyDocument

static void testVerifyDocument(CuTest *tc) {	int res;	unsigned char in[0x1ffff];	unsigned in_len = 0;	char doc[] = "LAPTOP";	FILE *f = NULL;	KSI_Signature *sig = NULL;	KSI_ERR_clearErrors(ctx);	f = fopen(getFullResourcePath(TEST_SIGNATURE_FILE), "rb");	CuAssert(tc, "Unable to open signature file.", f != NULL);	in_len = (unsigned)fread(in, 1, sizeof(in), f);	CuAssert(tc, "Nothing read from signature file.", in_len > 0);	fclose(f);	res = KSI_Signature_parse(ctx, in, in_len, &sig);	CuAssert(tc, "Failed to parse signature", res == KSI_OK && sig != NULL);	res = KSI_Signature_verifyDocument(sig, ctx, doc, strlen(doc));	CuAssert(tc, "Failed to verify valid document", res == KSI_OK);	res = KSI_Signature_verifyDocument(sig, ctx, doc, sizeof(doc));	CuAssert(tc, "Verification did not fail with expected error.", res == KSI_VERIFICATION_FAILURE);	KSI_Signature_free(sig);}
开发者ID:khushil,项目名称:libksi,代码行数:32,


示例11: potion_test_empty

void potion_test_empty(CuTest *T) {  PN empty = PN_TUP0();  CuAssert(T, "empty isn't a tuple", PN_IS_TUPLE(empty));  CuAssert(T, "empty isn't a ref", PN_IS_PTR(empty));  CuAssertIntEquals(T, "tuple length is off",                    0, PN_INT(potion_send(empty, potion_str(P, "length"))));}
开发者ID:Scriptor,项目名称:potion,代码行数:7,


示例12: potion_test_allocated

void potion_test_allocated(CuTest *T) {  struct PNMemory *M = P->mem;  void *prev = NULL;  void *scanptr = (void *)((char *)M->birth_lo + PN_ALIGN(sizeof(struct PNMemory), 8));  while ((PN)scanptr < (PN)M->birth_cur) {    if (((struct PNFwd *)scanptr)->fwd != POTION_FWD && ((struct PNFwd *)scanptr)->fwd != POTION_COPIED) {      if (((struct PNObject *)scanptr)->vt > PN_TUSER) {	vPN(Object) o = (struct PNObject *)scanptr;	fprintf(stderr, "error: scanning heap from %p to %p/n",		M->birth_lo, M->birth_cur);	fprintf(stderr, "%p in %s region/n", scanptr,		IS_GC_PROTECTED(scanptr) ? "protected"		: IN_BIRTH_REGION(scanptr) ? "birth"		: IN_OLDER_REGION(scanptr) ? "older"		: "gc");	fprintf(stderr, "%p { uniq:0x%08x vt:0x%08x ivars[0]:0x%08lx type:0x%x}/n",		scanptr, o->uniq, o->vt, o->ivars[0],		potion_type((PN)scanptr));	fprintf(stderr, "prev %p: size=%d, type:0x%x (%s)/n",		prev, potion_type_size(P, prev),		potion_type((PN)prev), AS_STR(PN_VTABLE(PN_TYPE((PN)prev))));#ifdef DEBUG	//potion_dump_stack(P);#endif      }      CuAssert(T, "wrong type for allocated object", ((struct PNObject *)scanptr)->vt <= PN_TUSER);    }    prev = scanptr;    scanptr = (void *)((char *)scanptr + potion_type_size(P, scanptr));    CuAssert(T, "allocated object goes beyond GC pointer", (PN)scanptr <= (PN)M->birth_cur);  }}
开发者ID:Scriptor,项目名称:potion,代码行数:32,


示例13: createIndex

void createIndex(CuTest* tc, Directory* dir, bool multiSegment) {    WhitespaceAnalyzer whitespaceAnalyzer;    IndexWriter w(dir, &whitespaceAnalyzer, true);    w.setMergePolicy(_CLNEW LogDocMergePolicy());    Document doc;    for (int i = 0; i < 100; i++) {        createDocument(doc, i, 4);        w.addDocument(&doc);        if (multiSegment && (i % 10) == 0) {            w.flush();        }    }    if (!multiSegment) {        w.optimize();    }    w.close();    IndexReader* r = IndexReader::open(dir);    if (multiSegment) {        CuAssert(tc,_T("check is multi"), strcmp(r->getObjectName(),"MultiSegmentReader")==0);    } else {        CuAssert(tc,_T("check is segment"), strcmp(r->getObjectName(),"SegmentReader")==0);    }    r->close();    _CLDELETE(r);}
开发者ID:Beirdo,项目名称:beirdobot,代码行数:29,


示例14: addInput

static void addInput(CuTest *tc, KSI_BlockSigner *bs, int genMeta) {	int res = KSI_UNKNOWN_ERROR;	size_t i;	KSI_DataHash *hsh = NULL;	KSI_MetaData *md = NULL;	for (i = 0; input_data[i] != NULL; i++) {		res = KSI_DataHash_create(ctx, input_data[i], strlen(input_data[i]), KSI_HASHALG_SHA2_256, &hsh);		CuAssert(tc, "Unable to create data hash.", res == KSI_OK && hsh != NULL);		if (genMeta) {			char clientId[100];			KSI_snprintf(clientId, sizeof(clientId), "Client-%d", i);			res = createMetaData(clientId, &md);			CuAssert(tc, "Unable to create metadata.", res == KSI_OK && md != NULL);			res = KSI_BlockSigner_addLeaf(bs, hsh, 0, md, NULL);			CuAssert(tc, "Unable to add leaf with meta data.", res == KSI_OK);			KSI_MetaData_free(md);			md = NULL;		} else {			res = KSI_BlockSigner_add(bs, hsh);			CuAssert(tc, "Unable to add data hash to the block signer.", res == KSI_OK);		}		KSI_DataHash_free(hsh);		hsh = NULL;	}}
开发者ID:GuardTime,项目名称:libksi,代码行数:30,


示例15: rbtree_1

static void rbtree_1(CuTest *tc){	/* tree should be empty on start. */	CuAssert(tc, "empty tree?", (rbtree_first((rbtree_t*)tree) == &rbtree_null_node));	CuAssert(tc, "empty tree?", (rbtree_last((rbtree_t*)tree) == &rbtree_null_node));	test_tree_integrity(tc, tree);}
开发者ID:LTD-Beget,项目名称:nsd,代码行数:7,


示例16: testVerifyCalendarChainAlgoChange

static void testVerifyCalendarChainAlgoChange(CuTest *tc) {	int res;	unsigned char in[0x1ffff];	unsigned in_len = 0;	FILE *f = NULL;	KSI_Signature *sig = NULL;	KSI_ERR_clearErrors(ctx);	f = fopen(getFullResourcePath("resource/tlv/cal_algo_switch.ksig"), "rb");	CuAssert(tc, "Unable to open signature file.", f != NULL);	in_len = (unsigned)fread(in, 1, sizeof(in), f);	CuAssert(tc, "Nothing read from signature file.", in_len > 0);	fclose(f);	res = KSI_Signature_parse(ctx, in, in_len, &sig);	CuAssert(tc, "Failed to parse signature", res == KSI_OK && sig != NULL);	KSITest_setFileMockResponse(tc, getFullResourcePath("resource/tlv/cal_algo_switch-extend_resposne.tlv"));	ctx->requestCounter = 0;	res = KSI_Signature_verifyOnline(sig, ctx);	CuAssert(tc, "Failed to verify valid document", res == KSI_OK);	KSI_Signature_free(sig);}
开发者ID:khushil,项目名称:libksi,代码行数:31,


示例17: testGetOldest

static void testGetOldest(CuTest *tc) {	int res;	KSI_MultiSignature *ms = NULL;	KSI_DataHash *hsh = NULL;	KSI_Signature *sig = NULL;	KSI_Integer *tm = NULL;	res = KSI_MultiSignature_fromFile(ctx, getFullResourcePath("resource/multi_sig/test2.mksi"), &ms);	CuAssert(tc, "Unable to read multi signature container from file.", res == KSI_OK && ms != NULL);	KSITest_DataHash_fromStr(ctx, "0111a700b0c8066c47ecba05ed37bc14dcadb238552d86c659342d1d7e87b8772d", &hsh);	res = KSI_MultiSignature_get(ms, hsh, &sig);	CuAssert(tc, "Unable to get signature from container.", res == KSI_OK && sig != NULL);	res = KSI_verifySignature(ctx, sig);	CuAssert(tc, "Unable to verify signature extracted from container.", res == KSI_OK);	res = KSI_Signature_getSigningTime(sig, &tm);	CuAssert(tc, "Wrong signing time (probably returning the newer signature).", res == KSI_OK && KSI_Integer_equalsUInt(tm, 1398866256));	KSI_Signature_free(sig);	KSI_DataHash_free(hsh);	KSI_MultiSignature_free(ms);}
开发者ID:GuardTime,项目名称:libksi,代码行数:25,


示例18: testLoadPublicationsFileWithNoCerts

static void testLoadPublicationsFileWithNoCerts(CuTest *tc) {	int res;	KSI_PublicationsFile *pubFile = NULL;	KSI_LIST(KSI_CertificateRecord) *certList = NULL;	KSI_PKICertificate *cert = NULL;	unsigned char dummy[] = {0xca, 0xfe, 0xba, 0xbe};	KSI_OctetString *certId = NULL;	KSI_ERR_clearErrors(ctx);	res = KSI_PublicationsFile_fromFile(ctx, getFullResourcePath("resource/publications/publications-nocerts.bin"), &pubFile);	CuAssert(tc, "Unable to read publications file", res == KSI_OK && pubFile != NULL);	res = KSI_PublicationsFile_getCertificates(pubFile, &certList);	CuAssert(tc, "Unable to get certificate list", res == KSI_OK);	CuAssert(tc, "Unexpected certificate list length.", KSI_CertificateRecordList_length(certList) == 0);	res = KSI_OctetString_new(ctx, dummy, sizeof(dummy), &certId);	CuAssert(tc, "Creating an octetstring failed", res == KSI_OK && certId != NULL);	res = KSI_PublicationsFile_getPKICertificateById(pubFile, certId, &cert);	CuAssert(tc, "Searching for a non existend certificate failed", res == KSI_OK && cert == NULL);	KSI_OctetString_free(certId);	KSI_PublicationsFile_free(pubFile);}
开发者ID:GuardTime,项目名称:libksi,代码行数:27,


示例19: testVerifyPublicationsFileWithAttributeNotPresent

static void testVerifyPublicationsFileWithAttributeNotPresent(CuTest *tc) {	int res;	KSI_PublicationsFile *pubFile = NULL;	KSI_CertConstraint arr[] = {			{NULL, NULL},			{NULL, NULL}	};	KSI_ERR_clearErrors(ctx);	res = KSI_PublicationsFile_fromFile(ctx, getFullResourcePath(TEST_PUBLICATIONS_FILE), &pubFile);	CuAssert(tc, "Unable to read publications file", res == KSI_OK && pubFile != NULL);	arr[0].oid = "2.5.4.9";	arr[0].val = "Local pub";	res = KSI_CTX_setDefaultPubFileCertConstraints(ctx, arr);	CuAssert(tc, "Unable to delete OID 2.5.4.9", res == KSI_OK);	/* Verification should fail. */	res = KSI_PublicationsFile_verify(pubFile, ctx);	CuAssert(tc, "Publications file must verify with address.", res != KSI_OK);	arr[0].oid = KSI_CERT_EMAIL;	arr[0].val = "[email
C++ CuAssertDblEquals函数代码示例
C++ Ctxt函数代码示例
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。