RTOS任務(wù)進(jìn)行單元測(cè)試的4種策略
https://www.beningo.com/4-tactics-to-unit-test-rtos-tasks/
超過(guò)50%的嵌入式軟件項(xiàng)目使用實(shí)時(shí)操作系統(tǒng)(RTOS)。不幸的是,使用RTOS會(huì)給使用現(xiàn)代開(kāi)發(fā)技術(shù)(如測(cè)試驅(qū)動(dòng)開(kāi)發(fā)(TDD)、DevOps或自動(dòng)測(cè)試)的開(kāi)發(fā)者帶來(lái)一些問(wèn)題。例如,當(dāng)開(kāi)發(fā)者試圖為他們的任務(wù)編寫(xiě)測(cè)試時(shí),他們遇到的第一個(gè)問(wèn)題是任務(wù)函數(shù)包含一個(gè)無(wú)限循環(huán)!任何直接調(diào)用任務(wù)函數(shù)的測(cè)試都會(huì)被認(rèn)為是一個(gè)無(wú)限循環(huán)!因此,任何直接調(diào)用任務(wù)函數(shù)的測(cè)試將永遠(yuǎn)不會(huì)完成。這篇文章將探討對(duì)RTOS任務(wù)進(jìn)行單元測(cè)試的幾種策略,其中包括:
- 循環(huán)的重新定義
- 完成信號(hào)
- 任務(wù)排除
- 通過(guò)OSAL使用主機(jī)線(xiàn)程(強(qiáng)烈建議)。
注意:在這篇文章中,我們將把任務(wù)和線(xiàn)程作為同義詞。我們還將使用ThreadX作為RTOS的例子。
(相關(guān)資料圖)
任務(wù)的剖析
在RTOS任務(wù)中,有幾個(gè)部分用于管理任務(wù)行為。首先,初始化部分聲明變量,實(shí)例化對(duì)象,初始化驅(qū)動(dòng)程序,并負(fù)責(zé)將傳遞給任務(wù)的任何數(shù)據(jù)轉(zhuǎn)換成正確的類(lèi)型。接下來(lái),有一個(gè)無(wú)限循環(huán),執(zhí)行所有任務(wù)的行為。例如,如果我們寫(xiě)了管理傳感器的任務(wù),我們希望任務(wù)的無(wú)限循環(huán)能定期檢索和處理傳感器的數(shù)據(jù)。最后,任務(wù)完成部分規(guī)定了任務(wù)完成后的情況。
典型的任務(wù)使用ThreadX可能看起來(lái)像下面的代碼片段:
{ void Task_Sensors(ULONG ThreadInput) { // SECTION 1: Initialization (void) ThreadInput; SensorData_t SensorRawData; SensorData_t SensorData; SensorData_t pSensorDataTx = &SensorData; Sensor_Init(); // SECTION 2: Tasks main function / behavior / purpose while(true) { SensorRawData = Sensor_Sample(); SensorData = SensorProcess(SensorRawData); (void)tx_queue_send(SensorTxQ, (void *)&pSensorDataTx, TX_WAIT_FOREVER); tx_thread_sleep(TASK_SENSORS_PERIOD_MS); } // SECTION 3: TasK Completion Activities }
我發(fā)現(xiàn),編寫(xiě)周期性任務(wù)的開(kāi)發(fā)人員希望他們的任務(wù)能夠無(wú)限期地運(yùn)行,而沒(méi)有考慮如果任務(wù)運(yùn)行到完成會(huì)發(fā)生什么。
看看這個(gè)任務(wù),你可以看到,如果一個(gè)開(kāi)發(fā)者想在測(cè)試中對(duì)Task_Sensors進(jìn)行調(diào)用,他們會(huì)遇到幾個(gè)問(wèn)題。因此,讓我們來(lái)看看這些問(wèn)題,并按照我經(jīng)??吹降拈_(kāi)發(fā)人員在達(dá)成最直接和最好的解決方案之前所嘗試的各種策略。
參考資料
- 軟件測(cè)試精品書(shū)籍文檔下載持續(xù)更新 https://github.com/china-testing/python-testing-examples 請(qǐng)點(diǎn)贊,謝謝!
- 本文涉及的python測(cè)試開(kāi)發(fā)庫(kù) 謝謝點(diǎn)贊! https://github.com/china-testing/python_cn_resouce
- python精品書(shū)籍下載 https://github.com/china-testing/python_cn_resouce/blob/main/python_good_books.md
循環(huán)的重新定義
經(jīng)常看到工程師部署的第一個(gè)戰(zhàn)術(shù)是循環(huán)重定義。循環(huán)的重新定義是指根據(jù)代碼是生產(chǎn)代碼還是測(cè)試代碼,對(duì)任務(wù)中的無(wú)限循環(huán)進(jìn)行操作。例如,Task_Sensor的代碼將被改寫(xiě)為如下內(nèi)容:
void Task_Sensors(ULONG ThreadInput) { // SECTION 1: Initialization (void) ThreadInput; SensorData_t SensorRawData; SensorData_t SensorData; SensorData_t pSensorDataTx = &SensorData; Sensor_Init(); // SECTION 2: Tasks main function / behavior / purpose while(LOOP_STATE) { SensorRawData = Sensor_Sample(); SensorData = SensorProcess(SensorRawData); (void)tx_queue_send(SensorTxQ, (void *)&pSensorDataTx, TX_WAIT_FOREVER); tx_thread_sleep(TASK_SENSORS_PERIOD_MS); } // SECTION 3: TasK Completion Activities }
這個(gè)想法是,開(kāi)發(fā)人員可以創(chuàng)建有條件編譯的代碼,以控制循環(huán)是永遠(yuǎn)運(yùn)行還是一次。這段代碼通常看起來(lái)像下面這樣:
#ifdef PRODUCTION #define LOOP_STATE true #else #define LOOP_STATE false #endif
除了編譯后的代碼外,構(gòu)建時(shí)還必須定義或不定義PRODUCTION宏。
一般來(lái)說(shuō),這不是使RTOS任務(wù)可測(cè)試的好方法,有幾個(gè)原因。首先,我們正在測(cè)試的代碼正在改變。我們的任務(wù)在測(cè)試過(guò)程中的行為會(huì)與運(yùn)行時(shí)的行為不同。第二,我們正在添加有條件編譯的代碼,這通常不是很干凈。第三,在定義宏的過(guò)程中,有可能出現(xiàn)人為錯(cuò)誤。最后,雖然循環(huán)的重新定義對(duì)于Task_Sensor來(lái)說(shuō)似乎很有吸引力,但測(cè)試任務(wù)的相互作用會(huì)變得過(guò)于復(fù)雜。事實(shí)上,如果我們需要循環(huán)運(yùn)行三到四次會(huì)發(fā)生什么?我們現(xiàn)在需要為L(zhǎng)OOP_STATE定義獨(dú)特的定義。
完成信號(hào)
完成信號(hào)是對(duì)循環(huán)重定義思想的修改,允許任務(wù)無(wú)限期地運(yùn)行,直到收到任務(wù)應(yīng)該停止執(zhí)行的信號(hào)。在這種情況下,任務(wù)代碼被修改為刪除宏定義,轉(zhuǎn)而使用循環(huán)變量,如下圖所示:
void Task_Sensors(ULONG ThreadInput) { // SECTION 1: Initialization (void) ThreadInput; bool isRunning = true; SensorData_t SensorRawData; SensorData_t SensorData; SensorData_t pSensorDataTx = &SensorData; Sensor_Init(); // SECTION 2: Tasks main function / behavior / purpose while(isRunning) { SensorRawData = Sensor_Sample(); SensorData = SensorProcess(SensorRawData); (void)tx_queue_send(SensorTxQ, (void *)&pSensorDataTx, TX_WAIT_FOREVER); tx_thread_sleep(TASK_SENSORS_PERIOD_MS); isRunning = Task_GetDesiredRunState(TASK_SENSOR); } // SECTION 3: TasK Completion Activities }
正如你所看到的,在任務(wù)結(jié)束時(shí),我們檢查該任務(wù)是否仍在運(yùn)行。這就解決了運(yùn)行多個(gè)循環(huán)的問(wèn)題,并通過(guò)刪除宏來(lái)清理代碼。然而,我們現(xiàn)在已經(jīng)為任務(wù)的運(yùn)行引入了復(fù)雜性,并為內(nèi)存損壞或單一事件干擾(SEU)打開(kāi)了機(jī)會(huì),以改變isRunning的狀態(tài)并完成我們的任務(wù)。
任務(wù)在生產(chǎn)中運(yùn)行到完成似乎不是什么大問(wèn)題,但不是所有的實(shí)時(shí)操作系統(tǒng)都能優(yōu)雅地處理這個(gè)問(wèn)題。例如,如果你允許FreeRTOS的任務(wù)運(yùn)行到完成,內(nèi)核就會(huì)窒息并停止執(zhí)行所有的代碼!
任務(wù)排除法
當(dāng)我們不測(cè)試我們的任務(wù)時(shí),任務(wù)排除就發(fā)生了!我們不需要測(cè)試任務(wù)!而不是試圖從測(cè)試線(xiàn)束中調(diào)用任務(wù),我們創(chuàng)建測(cè)試來(lái)運(yùn)行任務(wù)本身的代碼。 任務(wù)排除要求我們重寫(xiě)我們的函數(shù),使其看起來(lái)像下面這樣:
void Task_Sensors(ULONG ThreadInput) { // SECTION 1: Initialization (void) ThreadInput; Task_SensorInit(); // SECTION 2: Tasks main function / behavior / purpose while(true) { Task_SensorRun(); tx_thread_sleep(TASK_SENSORS_PERIOD_MS); } // SECTION 3: TasK Completion Activities } /********************************** * Placed in a different module **********************************/ void Task_SensorInit(void) { SensorData_t SensorRawData; SensorData_t SensorData; SensorData_t pSensorDataTx = &SensorData; Sensor_Init(); } void Task_SensorRun(void) { SensorRawData = Sensor_Sample(); SensorData = SensorProcess(SensorRawData); (void)tx_queue_send(SensorTxQ, (void *)&pSensorDataTx, TX_WAIT_FOREVER); }
老實(shí)說(shuō),上面的代碼就是任務(wù)應(yīng)該有的樣子。這段代碼非常干凈,也很容易理解。但問(wèn)題是,我們是通過(guò)嘗試使用一種不太理想的技術(shù)來(lái)達(dá)到這個(gè)目的的。
我們現(xiàn)在在Task_Sensors中看到的任務(wù)代碼非常簡(jiǎn)單,任務(wù)排除會(huì)說(shuō)我們不需要測(cè)試它。因此,相反,我們將在我們的測(cè)試線(xiàn)束中測(cè)試Task_SensorInit和Task_SensorRun函數(shù)。畢竟,這些函數(shù)被保存在一個(gè)單獨(dú)的模塊中,所以我們可以將任務(wù)代碼從測(cè)試線(xiàn)束中排除,實(shí)現(xiàn)我們所期望的100%的代碼覆蓋,對(duì)嗎?
任務(wù)排除的問(wèn)題是,在我們?cè)谀繕?biāo)上運(yùn)行應(yīng)用程序之前,我們永遠(yuǎn)不會(huì)測(cè)試任務(wù)代碼。不幸的是,我們也欺騙自己,認(rèn)為我們的測(cè)試覆蓋了所有的代碼。
優(yōu)點(diǎn)是我們可以根據(jù)需要從測(cè)試中調(diào)用任務(wù)中的函數(shù)。我們已經(jīng)實(shí)現(xiàn)了這一點(diǎn),并避免了需要處理無(wú)限的while循環(huán)的問(wèn)題。代碼更加簡(jiǎn)潔,我們也沒(méi)有創(chuàng)建一堆條件性編譯語(yǔ)句。
雖然這種技術(shù)可以使測(cè)試任務(wù)代碼更容易,但從技術(shù)上講,它不是在測(cè)試任務(wù)代碼。相反,它是一種變通方法。為了測(cè)試你的任務(wù)代碼,你應(yīng)該嘗試在你的主機(jī)上創(chuàng)建一個(gè)線(xiàn)程或任務(wù),并在那里運(yùn)行這些代碼。
通過(guò)OSAL使用主機(jī)線(xiàn)程(強(qiáng)烈建議)。
測(cè)試RTOS任務(wù)的真正問(wèn)題與大多數(shù)任務(wù)有while語(yǔ)句的事實(shí)無(wú)關(guān)。相反,這個(gè)問(wèn)題來(lái)自于開(kāi)發(fā)者對(duì)測(cè)試的思考和方法。到目前為止,我們所研究的所有策略都假定我們想直接從我們的測(cè)試線(xiàn)束中調(diào)用Task_Sensors。這就是問(wèn)題所在。在我們的測(cè)試線(xiàn)束中,我們想創(chuàng)建一個(gè)運(yùn)行的Task_Sensors任務(wù)或線(xiàn)程,而不是進(jìn)行函數(shù)調(diào)用!這就是問(wèn)題所在!
我們測(cè)試?yán)Ь车母驹蚴?,開(kāi)發(fā)人員沒(méi)有利用操作系統(tǒng)抽象層(OSAL)。相反,他們直接進(jìn)入RTOS的API并使用這些API。雖然調(diào)用RTOS APIs很快,而且似乎是一個(gè)很好的方法,但它是將RTOS與應(yīng)用程序代碼緊密地耦合在一起。這種耦合使得測(cè)試正確使用任務(wù)或線(xiàn)程的應(yīng)用程序代碼變得非常困難。
最佳的方法是將RTOS的細(xì)節(jié)隱藏在操作系統(tǒng)抽象層(OSAL)的后面。例如,如果你檢查我們到目前為止所看到的各種版本的Task_Sensors,你會(huì)發(fā)現(xiàn)我們正在使用ThreadX tx_queue_send API來(lái)發(fā)送消息到隊(duì)列。因此,我們應(yīng)該把這些細(xì)節(jié)放在OSAL后面,這樣我們的任務(wù)就會(huì)像下面這樣:
void Task_Sensors(ULONG ThreadInput) { // SECTION 1: Initialization (void) ThreadInput; bool isRunning = true; SensorData_t SensorRawData; SensorData_t SensorData; SensorData_t pSensorDataTx = &SensorData; Sensor_Init(); // SECTION 2: Tasks main function / behavior / purpose while(true) { SensorRawData = Sensor_Sample(); SensorData = SensorProcess(SensorRawData); (void)OSAL_Q_Send(SensorTxQ, (void *)&pSensorDataTx, OS_WAIT_FOREVER); tx_thread_sleep(TASK_SENSORS_PERIOD_MS); } // SECTION 3: TasK Completion Activities }
OSAL_Q_Send是一個(gè)抽象,我們的應(yīng)用程序代碼使用它來(lái)發(fā)送隊(duì)列中的數(shù)據(jù)。應(yīng)用程序不應(yīng)該關(guān)心我們是否在使用ThreadX、FreeRTOS、pthread或任何其他RTOS或任務(wù)調(diào)度器。根據(jù)我們想要編譯代碼的系統(tǒng),會(huì)提供一個(gè)實(shí)現(xiàn)文件。這樣做有很多好處,比如說(shuō):
- 應(yīng)用程序不與實(shí)時(shí)操作系統(tǒng)相聯(lián)系
- 測(cè)試可以使用主機(jī)的線(xiàn)程框架
- 應(yīng)用程序是可移植和可重復(fù)使用的
- 避免了臨時(shí)性的和黑客式的測(cè)試方法進(jìn)行測(cè)試。
對(duì)于許多對(duì)使用DevOps和自動(dòng)測(cè)試線(xiàn)束感興趣的開(kāi)發(fā)者來(lái)說(shuō),你可能至少有針對(duì)你所選擇的RTOS和pthread的實(shí)現(xiàn),pthread是Linux的POSIX線(xiàn)程庫(kù)。不幸的是,我們?nèi)绾问褂胮thread以及設(shè)計(jì)和構(gòu)建OSAL已經(jīng)超出了今天的范圍,但我們將在未來(lái)探討這些話(huà)題。
現(xiàn)在,如果你有興趣看一些OSAL的例子,我推薦你看一下CMSIS-RTOS-V2和NASA的Aeronautics GSC-18730-1。有可能,對(duì)于你的需求來(lái)說(shuō),這些都是過(guò)剩的,但它們是完全實(shí)現(xiàn)OSAL的好例子。我建議探索它們,并慢慢設(shè)計(jì)和建立你的OSAL,你可以在你所有的應(yīng)用程序中使用。
小結(jié)
有幾種策略可以讓開(kāi)發(fā)者用來(lái)對(duì)任務(wù)或線(xiàn)程進(jìn)行單元測(cè)試。正如我們?cè)诮裉斓奈恼轮兴吹降模蠖鄶?shù)開(kāi)發(fā)人員可以部署的戰(zhàn)術(shù)都是針對(duì)未能將其任務(wù)架構(gòu)為使用OSAL的變通方法。一旦有了OSAL,任務(wù)代碼就可以通過(guò)提供抽象層背后的必要功能,使用任何RTOS或本地線(xiàn)程庫(kù)進(jìn)行測(cè)試。OSAL層有助于:
- 簡(jiǎn)化測(cè)試策略
- 保持代碼的清潔
- 提高靈活性、可移植性和重用性
如果你想測(cè)試你所有的代碼,那么通過(guò)OSAL來(lái)利用pthread是最好的方法。
關(guān)鍵詞:
您可能也感興趣:
今日熱點(diǎn)
為您推薦
高途 9 周年,陳向東:投入重資、多團(tuán)隊(duì)探索 GPT 相關(guān)方向 世界最資訊
世界播報(bào):惠州一百萬(wàn)人,月繳1000元,都不知道公積金有這個(gè)BUG!
天天消息!50角鋼每米重量是多少_50角鋼每米重量
更多
- 科沃斯618全周期成績(jī)釋出,穩(wěn)居行業(yè)第一,發(fā)揮龍頭領(lǐng)跑優(yōu)勢(shì)
- 速看:福建省五一幼兒園項(xiàng)目全面封頂
- 京城首現(xiàn)門(mén)窗甄選館 沃倫門(mén)窗開(kāi)賣(mài)咖啡_環(huán)球熱消息
- 臺(tái)灣又一明星翻車(chē),性侵20人不止,受害者:下面很大、最?lèi)?ài)絲襪
- 坦克500 Hi4-T將于6月26日正式上市-環(huán)球熱點(diǎn)
- 存款利率降了 對(duì)我們有哪些影響?
- 中國(guó)電力建設(shè)發(fā)展大會(huì)賦能電力高質(zhì)量發(fā)展
- 香港自資院校內(nèi)地生大增,樹(shù)仁大學(xué)較去年多1.6倍
更多
- 許錦波當(dāng)選國(guó)際計(jì)算生物學(xué)學(xué)會(huì)Fellow|焦點(diǎn)熱訊
- 不聽(tīng)不聽(tīng)王八念經(jīng)下一句
- 靜電除塵拖把好用嗎,當(dāng)然好用 天天觀焦點(diǎn)
- 南財(cái)快評(píng):物流高質(zhì)量發(fā)展應(yīng)如何推進(jìn)?
- 外媒:土耳其將最低工資再提高34%應(yīng)對(duì)高通脹 去年已提高1倍
- 【追蹤】物業(yè)拒絕賣(mài)電愁壞水果店,《小里幫忙》后開(kāi)發(fā)商補(bǔ)償5...
- 環(huán)球即時(shí)看!大樂(lè)透曬票第070期,你所看到的驚艷都曾被平庸歷練
- 熱點(diǎn)聚焦:金山云港股跌8.74%
排行
- 【組圖】三明泰寧:非遺進(jìn)校園 文化共傳承 新動(dòng)態(tài)
- 古裝劇雷同現(xiàn)實(shí)劇抬頭 "腦洞劇"走紅反映觀眾訴求
- 來(lái)不及減肥也可以瘦5斤
- 南京老舊小區(qū)增梯 已有1463部簽訂協(xié)議
- 2018型男們的選包方案!
- 新房裝好一年多墻壁脫落
- 制造行業(yè)升級(jí)大勢(shì)所趨 可加速制造強(qiáng)國(guó)建設(shè)步伐
- 我國(guó)首個(gè)海上智能氣田群——東方氣田群全面建成
- 全新智能產(chǎn)業(yè)體系建立,中國(guó)智能產(chǎn)業(yè)將邁上更高的臺(tái)階
- 上海浦東新區(qū)人工智能技能大賽舉行
最近更新
- RTOS任務(wù)進(jìn)行單元測(cè)試的4種策略
- 郵儲(chǔ)銀行株洲市分行開(kāi)展《反電信網(wǎng)絡(luò)詐騙法》宣傳活動(dòng)
- 全球今熱點(diǎn):實(shí)名曝光!大連14人終生禁駕
- 一線(xiàn)采風(fēng)|粽香迎端午 巾幗暖人心
- 兒童入托入學(xué)需查驗(yàn)疫苗接種證明,梧州市民可提前在網(wǎng)上自助...
- 實(shí)時(shí):賞非遺賽龍舟品美食 廣西玉林端午文化盛宴引客來(lái)
- 世界最新:走出世界!掘金拉美2023拉美跨境電商產(chǎn)業(yè)帶高峰論...
- 出口商品竟是“冒牌貨” 廣州港航公安迅速破案 世界最新
- 全球熱訊:寧德時(shí)代電池有重大缺陷 已被特斯拉暫停供貨?寧德...
- 8363人!三亞萬(wàn)科公園里安居房項(xiàng)目申報(bào)審核結(jié)果出爐
- 今日觀點(diǎn)!60余位詩(shī)人、作家端午節(jié)前走進(jìn)彭州,以文學(xué)之力助力...
- 列車(chē)上乘客暈倒 甘肅臨澤護(hù)士呂婷婷緊急救助
- 高質(zhì)量發(fā)展調(diào)研行|福州:“數(shù)治”帶來(lái)高品質(zhì)生活
- 句容稅務(wù):送稅法進(jìn)高校 “稅”助力向未來(lái) 全球微速訊
- 北海市財(cái)政局:“四個(gè)一” 創(chuàng)新建立政府采購(gòu)信用體系
- 今頭條!泉峰汽車(chē)最新公告:終止實(shí)施2022年限制性股票激勵(lì)計(jì)...
- 中航證券:給予東方電氣買(mǎi)入評(píng)級(jí)_全球視點(diǎn)
- 天天快播:“你是不是開(kāi)通了會(huì)員,每個(gè)月要扣500元......”小...
- 當(dāng)前報(bào)道:vivo V29或在未來(lái)幾周亮相 搭載驍龍778G+移動(dòng)平臺(tái)
- 減脂時(shí),是不是不能吃豬肉?
- 3歲孩子吃牛肉和什么菜配好。? 看點(diǎn)
- 阿米番茄牛腩的做法正宗?
- 當(dāng)前熱門(mén):巨灣技研發(fā)布“鳳凰電池”,中低壓平臺(tái)也能實(shí)現(xiàn)超快充
- “千名大學(xué)生看奉賢”暨“發(fā)現(xiàn)奉賢”短視頻征集大賽啟動(dòng)
- 全球消息!鄰里贈(zèng)祝福 端午粽飄香
- 內(nèi)地端午假期預(yù)計(jì)旅游人次達(dá)1億 旅游消費(fèi)達(dá)370億 每日視訊
- 【全球新視野】?jī)?nèi)蒙古自治區(qū)達(dá)拉特旗發(fā)布高溫黃色預(yù)警
- 小米巨省電新一級(jí)空調(diào)上架:1.5匹、直降550元 世界通訊
- 每日關(guān)注!不朽者傳奇跳票到8月22
- 自動(dòng)下載!《最終幻想16》已開(kāi)啟預(yù)載-環(huán)球觀焦點(diǎn)
今日要聞
- 列車(chē)上乘客暈倒 甘肅臨澤護(hù)士呂婷婷緊急救助
- 天天熱訊:【程序源代碼】人工智能ChatGPT實(shí)現(xiàn)的微信小程序
- 招商局港口(00144)擬透過(guò)以股代息方式派付末期股息
- 許錦波當(dāng)選國(guó)際計(jì)算生物學(xué)學(xué)會(huì)Fellow|焦點(diǎn)熱訊
- 天天快播:“你是不是開(kāi)通了會(huì)員,每個(gè)月要扣500元......”小心,這是詐騙!
- 電動(dòng)車(chē)戴頭盔規(guī)定2020 電動(dòng)車(chē)戴頭盔規(guī)定2020最新-天天速訊
- 科沃斯618全周期成績(jī)釋出,穩(wěn)居行業(yè)第一,發(fā)揮龍頭領(lǐng)跑優(yōu)勢(shì)
- 多家豬企探索全產(chǎn)業(yè)鏈布局 能否對(duì)沖豬價(jià)走低風(fēng)險(xiǎn)?
- AI生成的音樂(lè)能獲獎(jiǎng)嗎?格萊美獎(jiǎng)制定新規(guī)則_世界資訊
- 臨港集團(tuán)董事長(zhǎng)袁國(guó)華:“常熟綠洲芯城”是臨港集團(tuán)繼大豐園區(qū)之后又一大戰(zhàn)略落子