成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Apache Hadoop代碼質量:生產VS測試

大數據 Hadoop
讓我們看一下PVS-Studio靜態分析器警告,以查看測試錯誤并不比生產錯誤更嚴重這一事實的重要性。當今的焦點:Apache Hadoop。

為了獲得高質量的生產代碼,僅確保測試的最大覆蓋范圍還不夠。無疑,出色的結果需要主要的項目代碼和測試才能有效地協同工作。因此,測試必須與源代碼一樣受到重視。體面的測試是成功的關鍵因素,因為它將趕上生產的衰退。讓我們看一下PVS-Studio靜態分析器警告,以查看測試錯誤并不比生產錯誤更嚴重這一事實的重要性。當今的焦點:Apache Hadoop。 

Apache Hadoop代碼質量:生產VS測試

關于該項目

那些以前對大數據感興趣的人可能已經聽說過Apache Hadoop項目或與之合作。簡而言之,Hadoop是可以用作構建和使用大數據系統的基礎的框架。

Hadoop由四個主要模塊組成;他們每個人都執行Big Dat $$ anonymous $$ nalytics系統所需的特定任務:

  • Hadoop通用。
  • MapReduce。
  • Hadoop分布式文件系統。
  • YARN。

關于支票

如文檔中所示,PVS-Studio可以通過多種方式集成到項目中:

  • 使用Maven插件。
  • 使用Gradle插件。
  • 使用Gradle IntellJ IDEA。
  • 直接使用分析儀。

Hadoop基于Maven構建系統;因此,檢查沒有任何障礙。

在集成了文檔中的腳本并編輯了一個pom.xml文件(依賴項中有一些模塊不可用)之后,分析開始了!

分析完成后,我選擇了最有趣的警告,并注意到在生產代碼和測試中,我具有相同數量的警告。通常,我不考慮測試中的分析器警告。但是,當我將它們分開時,我無法不理會“測試”警告。我想:“為什么不看一下它們,因為測試中的錯誤也可能帶來不利的后果。” 它們可能導致錯誤或部分測試,甚至導致雜亂。

選擇最有趣的警告后,我將其分為以下幾類:生產,測試和四個主要Hadoop模塊。現在,我很高興對分析儀警告進行回顧。

生產代碼

Hadoop常見

V6033已經添加了具有相同鍵“ KDC_BIND_ADDRESS”的項目。MiniKdc.java(163),MiniKdc.java(162)

Java

  1. 1個公共 類 MiniKdc {2  ....3 私有 靜態 最終 Set < String >  
  2.  PROPERTIES  =  new  HashSet < String >();4  ....5 靜態 {6  性質。 
  3. 添加(ORG_NAME);7  性質。添加(ORG_DOMAIN);8  性質。添加 
  4. (KDC_BIND_ADDRESS);9  性質。添加(KDC_BIND_ADDRESS); // <=10  性 
  5. 質。加(KDC_PORT);11  性質。加(INSTANCE);12   ....13  }14  ....15} 

HashSet檢查項目時,a中兩次增加的值 是一個非常常見的缺陷。第二個添加項將被忽略。我希望這種重復只是一場不必要的悲劇。如果要添加另一個值怎么辦?

MapReduce

V6072找到兩個相似的代碼片段。也許這是一個錯字, localFiles應該使用變量代替 localArchives。

  • LocalDistributedCacheManager.java(183)。
  • LocalDistributedCacheManager.java(178)。
  • LocalDistributedCacheManager.java(176)。
  • LocalDistributedCacheManager.java(181)。

Java

  1. 1個公共 同步 無效 設置(JobConf  conf,JobID  jobId)拋出 IOException  
  2. {2  ....3 //使用本地化數據更新配置對象。4 如果(!localArchives。的 
  3. isEmpty()){5  conf。集(MRJobConfig。 
  4. CACHE_LOCALARCHIVES,StringUtils的6     。 
  5. arrayToString(localArchives。指定者(新 字符串 [ localArchives  //  
  6. <=7       。大小()])));8  }9 如果(!localFiles。的 
  7. isEmpty()){10  conf。集(MRJobConfig。 
  8. CACHE_LOCALFILES,StringUtils的11     。arrayToString(localFiles。指 
  9. 定者(新 字符串 [ localArchives    // <=12       。大小 
  10. ()])));13  }14  ....15} 

V6072診斷程序有時會產生一些有趣的發現。此診斷的目的是檢測由于復制粘貼和替換兩個變量而導致的相同類型的代碼片段。在這種情況下,某些變量甚至保持“不變”。

上面的代碼演示了這一點。在第一個塊中, localArchives變量用于第二個類似的片段 localFiles。如果您認真研究此代碼,而不是很快進行遍歷,這通常在代碼審閱時發生,那么您會注意到該片段,作者忘記了替換該 localArchives變量。

這種失態可能導致以下情況:

  • 假設我們有localArchives(大小= 4)和localFiles(大小= 2)。
  • 創建數組時 localFiles.toArray(new String[localArchives.size()]),最后兩個元素將為null(["pathToFile1", "pathToFile2", null, null])。
  • 然后, org.apache.hadoop.util.StringUtils.arrayToString將返回數組的字符串表示形式,其中最后的文件名將顯示為“ null”(“ pathToFile1,pathToFile2,null,null”)。

所有這些都將進一步傳遞,上帝只知道這種情況下會有什么樣的檢查。

V6007表達式'children.size()> 0'始終為true。Queue.java(347)

Java

  1. 1個boolean  isHierarchySameAs(Queue  newState){2  ....3 如果(孩子  
  2. ==  空 ||  孩子。大小()==  0){4   ....5  }6 否則 ,如果(孩子。大 
  3. 小()>  0)7  {8   ....9  }10  ....11} 

由于要單獨檢查元素數是否為0,因此進一步檢查children.size()> 0將始終為true。

HDFS

V6001在'%'運算符的左側和右側有相同的子表達式'this.bucketSize'。RollingWindow.java(79)。

Java

  1. 1個 RollingWindow(int  windowLenMs,int  numBuckets){2  buckets  =  
  2.  new  Bucket [ numBuckets ];3  forint  i  =  0 ; i  <  numBuckets ;  
  3. i ++){4   buckets [ i ] =  new  Bucket();5   }6  這個。windowLenMs  
  4.  =  windowLenMs ;7  這個。bucketSize  =  windowLenMs  /  numBuckets  
  5. ;8  如果(此。bucketSize  % bucketSize  !=  0){      // <=9   拋出 
  6.  新的 IllegalArgumentException(10     “滾動窗口中的存儲桶大小不是整 
  7. 數:windowLenMs =”11       +  windowLenMs  +  “ numBuckets =”“  + 
  8.   numBuckets);12   }13  } 

YARN

V6067兩個或更多案例分支執行相同的操作。TimelineEntityV2Converter.java(386),TimelineEntityV2Converter.java(389)。

Java

  1. 1個 公共 靜態 ApplicationReport2  
  2. convertToApplicationReport(TimelineEntity  實體)3{4  ....5 如果 
  3. (指標 !=  null){6  long  vcoreSeconds  =  0 ;7  long   
  4. memorySeconds  =  0 ;8  long  preemptedVcoreSeconds  =  0 ;9  long 
  5.   preemptedMemorySeconds  =  0 ;1011  對于(TimelineMetric  指標: 
  6. 指標){12   開關(度量。的getId()){13   case   
  7. ApplicationMetricsConstants。APP_CPU_METRICS:14    vcoreSeconds  
  8.  =  getAverageValue(度量。的GetValues。()的值());15    休息  
  9. ;16   case  ApplicationMetricsConstants。APP_MEM_METRICS:17    
  10.  memorySeconds  = ....;18歲    休息 ;19   case  
  11.  ApplicationMetricsConstants。APP_MEM_PREEMPT_METRICS:20     
  12. preemptedVcoreSeconds  = ....;             // <=21    休息 ;22    
  13. case  ApplicationMetricsConstants。APP_CPU_PREEMPT_METRICS:23   
  14.   preemptedVcoreSeconds  = ....;             // <=24    休息 ;25  
  15.   默認值:26    //不應該發生27    休息 ;28    }29   }30   ....31 
  16.   }32  ....33} 

相同的代碼片段位于兩個case分支中。到處都是!在大多數情況下,這不是真正的錯誤,而只是考慮重構switch語句的原因。對于當前的情況,情況并非如此。重復的代碼片段設置變量的值preemptedVcoreSeconds。如果仔細查看所有變量和常量的名稱,可能會得出結論,在這種情況下, if metric.getId() == APP_MEM_PREEMPT_METRICS必須為preemptedMemorySeconds變量設置 值,而不是 preemptedVcoreSeconds。在這方面,在switch語句之后,preemptedMemorySeconds將始終保持0,而的值 preemptedVcoreSeconds可能不正確。

V6046格式錯誤。期望使用不同數量的格式項。不使用的參數:2. AbstractSchedulerPlanFollower.java(186)

Java

  1. 1個@Override2市民 同步 無效 synchronizePlan(規劃 計劃,布爾  
  2. shouldReplan)3{4  ....5 嘗試6  {7   
  3. setQueueEntitlement(planQueueName,....);8  }9 捕獲(YarnException  
  4.  e)10  {11  LOG。警告(“嘗試為計劃{{}確定保留大小時發生異常”,12 
  5.        currResId,13       planQueueName,14       e);15  }16  ....17} 

planQueueName記錄時不使用該 變量。在這種情況下,要么復制太多,要么格式字符串未完成。但是我仍然要責備舊的復制粘貼,在某些情況下,將其粘貼在腳上真是太好了。

測試代碼

Hadoop常見

V6072找到兩個相似的代碼片段。也許這是一個錯字,應該使用'allSecretsB'變量而不是'allSecretsA'。

TestZKSignerSecretProvider.java(316),TestZKSignerSecretProvider.java(309),TestZKSignerSecretProvider.java(306),TestZKSignerSecretProvider.java(313)。

Java

  1. 1個public  void  testMultiple(整數 順序)引發 異常 {2   ....3   
  2. currentSecretA  =  secretProviderA。getCurrentSecret();4   
  3. allSecretsA  =  secretProviderA。getAllSecrets();5  斷言。 
  4. assertArrayEquals(secretA2,currentSecretA);6  斷言。的 
  5. assertEquals(2,allSecretsA。長度);     // <=7  斷言。 
  6. assertArrayEquals(secretA2,allSecretsA [ 0 ]);8  斷言。 
  7. assertArrayEquals(secretA1,allSecretsA [ 1 ]);910  currentSecretB   
  8. =  secretProviderB。getCurrentSecret();11  allSecretsB  =   
  9. secretProviderB。getAllSecrets();12  斷言。 
  10. assertArrayEquals(secretA2,currentSecretB);13  斷言。的 
  11. assertEquals(2,allSecretsA。長度);    // <=14  斷言。 
  12. assertArrayEquals(secretA2,allSecretsB [ 0 ]);15  斷言。 
  13. assertArrayEquals(secretA1,allSecretsB [ 1 ]);16   ....17} 

再次是V6072。仔細觀察變量allSecretsA和allSecretsB。

V6043考慮檢查“ for”運算符。迭代器的初始值和最終值相同。TestTFile.java(235)。

Java

  1. 1個私有 int  readPrepWithUnknownLength(掃描 儀掃描儀,int   
  2. start,int  n)2  引發 IOException {3 對于(int  i  =  start ; i  <   
  3. start ; i ++){4  字符串 鍵 =  字符串。格式(localFormatter,i);5   
  4. 字節 [] 讀取 =  readKey(掃描儀);6  assertTrue(“鍵不等于”,陣列。 
  5. 等號(鍵。的getBytes(),讀));7  嘗試 {8   讀取 =  讀取值(掃描 
  6. 儀);9   assertTrue(false);10   }11  抓(IOException  即){12   // 
  7. 應該拋出異常13   }14  字符串 值 =  “值”  +  鍵;15  讀取 =   
  8. readLongValue(掃描器,值。的getBytes()。長度);16  assertTrue(“n 
  9. 要相等的值”,陣列。等號(讀,值。的getBytes()));17  掃描儀。前進 
  10. ();18歲  }19 返回(start  +  n);20} 

始終是綠色的測試?=)。循環的一部分,即測試本身的一部分,將永遠不會執行。這是由于以下事實:for語句中的初始計數器值和最終計數器值相等 。結果,條件 i < start將立即變為假,從而導致這種行為。我瀏覽了測試文件,然后得出i < (start + n)必須在循環條件下編寫的結論 。

MapReduce

V6007表達式'byteAm <0'始終為false。DataWriter.java(322)

Java

  1. 個GenerateOutput  writeSegment(long  byteAm,OutputStream  out)2  
  2.  引發 IOException {3 long  headerLen  =  getHeaderLength();4  
  3. if(byteAm  <  headerLen){5  //沒有足夠的字節寫頭6  返回 新  
  4. GenerateOutput(0,0);7  }8 //調整標題長度9 byteAm-  =  headerLen  
  5. ;10 if(byteAm  <  0){   // <=11  byteAm  =  0 ;12  }13  ....14} 

條件 byteAm < 0始終為假。為了弄清楚,讓我們在上面的代碼再看一遍。如果測試執行達到了操作的要求 byteAm -= headerLen,則意味著 byteAm >= headerLen。從這里開始,減去后,該 byteAm值將永遠不會為負。那就是我們必須證明的。

HDFS

V6072找到兩個相似的代碼片段。也許這是一個錯字, normalFile應該使用變量代替 normalDir。TestWebHDFS.java(625),TestWebHDFS.java(615),TestWebHDFS.java(614),TestWebHDFS.java(624)

Java

  1. 1個public  void  testWebHdfsErasureCodingFiles()引發 異常 {2  
  2.  ....3 最終 路徑 normalDir  =  新 路徑(“ / dir”);4 dfs。 
  3. mkdirs(normalDir);5 最終 路徑 normalFile  =  新 路徑 
  4. (normalDir,“ file.log ”);6  ....7 //邏輯塊#18 時間filestatus  
  5.  expectedNormalDirStatus  =  DFS。getFileStatus(normalDir);9  
  6. FileStatus  actualNormalDirStatus  =  webHdfs。 
  7. getFileStatus(normalDir); // <=10 斷言。的 
  8. assertEquals(expectedNormalDirStatus。isErasureCoded(),11    
  9.         actualNormalDirStatus。isErasureCoded());12  
  10. ContractTestUtils。assertNotErasureCoded(dfs,normalDir);13  
  11. assertTrue(normalDir  +  “應具有擦除編碼中未設置”  +  
  12. ....);1415 //邏輯塊#216 時間filestatus  expectedNormalFileStatus  
  13.  =  DFS。getFileStatus(normalFile);17 FileStatus   
  14. actualNormalFileStatus  =  webHdfs。getFileStatus(normalDir); // 
  15.  <=18歲 斷言。的assertEquals(expectedNormalFileStatus。 
  16. isErasureCoded(),19           actualNormalFileStatus。 
  17. isErasureCoded());20 ContractTestUtils。 
  18. assertNotErasureCoded(dfs,normalFile);21 assertTrue(normalFile 
  19.   +  “應具有擦除編碼中未設置”  + ....);22} 

信不信由你,它又是V6072!只需跟隨變量 normalDir和 normalFile。

V6027通過調用同一函數來初始化變量。可能是錯誤或未優化的代碼。TestDFSAdmin.java(883),TestDFSAdmin.java(879)。

Java

  1. 1個私人 void  verifyNodesAndCorruptBlocks(2  最終 整數 numDn,3  
  2.  final  int  numLiveDn,4  final  int  numCorruptBlocks,5  final   
  3. int  numCorruptECBlockGroups,6  最終的 DFSClient  客戶端,7  最后的  
  4. long  最高PriorityLowRedundancyReplicatedBlocks,8  最后的 Long  最高 
  5. PriorityLowRedundancyECBlocks)9  引發 IOException10{11 / *初始化變 
  6. 量* /12  ....13 最后的 字符串 ExpectedCorruptedECBlockGroupsStr  =  
  7.  String。格式(14   “具有損壞的內部塊的塊組:%d”,15    
  8. numCorruptECBlockGroups);16 最后的 字符串的  
  9. highestPriorityLowRedundancyReplicatedBlocksStr17   =  字符串。格式 
  10. (18歲   “ \ t具有最高優先級的低冗余塊”  +19     “要恢 
  11. 復:%d”,20   maximumPriorityLowRedundancyReplicatedBlocks);21 最 
  12. 后的 字符串 highestPriorityLowRedundancyECBlocksStr  =  String。格式 
  13. (22   “ \ t具有最高優先級的低冗余塊”  +23     “要恢復:%d”,24   
  14.  maximumPriorityLowRedundancyReplicatedBlocks);25  ....26} 

在這個片段中,highestPriorityLowRedundancyReplicatedBlocksStr和highestPriorityLowRedundancyECBlocksStr用相同的值初始化。通常應該是這樣,但事實并非如此。變量的名稱又長又相似,因此復制粘貼的片段沒有進行任何更改也就不足為奇了。為了解決這個問題,在初始化highestPriorityLowRedundancyECBlocksStr變量時,作者必須使用輸入參數highestPriorityLowRedundancyECBlocks。此外,最有可能的是,他們仍然需要更正格式行。

V6019檢測不到代碼。可能存在錯誤。TestReplaceDatanodeFailureReplication.java(222)。

Java

  1. 1個私人 虛空2verifyFileContent(....,SlowWriter [] slowwriters)引發 
  2.  IOException3{4 LOG。信息(“驗證文件”);5 對(INT  我 =  0 ; 我 <  
  3.  slowwriters。長度 ; 我++){6  LOG。信息(slowwriters [ 我 ]。文件路 
  4. 徑 + ....);7  FSDataInputStream  in  =  null ;8  嘗試 {9   in  =   
  5. fs。開放(slowwriters [ 我 ]。文件路徑);10   forint  j  =  0,x ;;  
  6. j ++){11    x  =  in中。閱讀();12    如果((x)!=  - 1){13    
  7.   斷言。assertEquals(j,x);14     } 其他 {15     回報 ;16     }17 
  8.     }18歲   } 最后 {19   IOUtils。closeStream(in);20   }21  }22} 

分析儀抱怨i++無法更改循環中的計數器。這意味著在for (int i = 0; i < slowwriters.length; i++) {....}循環中最多將執行一次迭代。讓我們找出原因。在第一次迭代中,我們將線程與對應的文件鏈接起來,以slowwriters[0]供進一步閱讀。接下來,我們通過loop讀取文件內容for (int j = 0, x;; j++)。

如果我們讀取了一些相關的內容,我們會將讀取的字節與j計數器的當前值進行比較assertEquals(如果檢查不成功,則測試失敗)。

如果文件檢查成功,并且到達文件末尾(讀取為-1),則該方法退出。

因此,無論在檢查期間發生什么 slowwriters[0],都不會去檢查后續元素。最有可能的是break,必須使用a代替return。

YARN

V6019檢測不到代碼。可能存在錯誤。TestNodeManager.java(176)

Java

  1. 1個@測試2公共 無效 3testCreationOfNodeLabelsProviderService()引發 
  2.  InterruptedException {4 嘗試 {5   ....6  } catch(異常 e){7  斷言。 
  3. 失敗(“捕獲到異常”);8  e。printStackTrace();9  }10} 

在這種情況下,該 Assert.fail方法將中斷測試,并且在發生異常的情況下不會打印堆棧跟蹤。如果有關捕獲到的異常的消息在這里足夠多,則最好刪除打印堆棧跟蹤的記錄,以免造成混淆。如果需要打印,則只需交換它們。

已發現許多類似的片段:

  • V6019檢測不到代碼。可能存在錯誤。TestResourceTrackerService.java(928)。
  • V6019檢測不到代碼。可能存在錯誤。TestResourceTrackerService.java(737)。
  • V6019檢測不到代碼。可能存在錯誤。TestResourceTrackerService.java(685)。

V6072找到兩個相似的代碼片段。也許這是一個錯字, publicCache應該使用變量代替 usercache。

 

  1. TestResourceLocalizationService.java(315),  
  2. TestResourceLocalizationService.java(309),  
  3. TestResourceLocalizationService.java(307),  
  4. TestResourceLocalizationService.java(313)  
  5. Java 
  1. 1個@測試2公共 無效 testDirectoryCleanupOnNewlyCreatedStateStore()3  
  2.  拋出 IOException,URISyntaxException4{5  ....6 //驗證目錄創建7 對于 
  3. (路徑 p:localDirs){8  p  =  新 路徑((新 URI(p。的 
  4. toString()))。的getPath());910  //邏輯塊#111  路徑 usercache 
  5.   =  新 路徑(p,ContainerLocalizer。USERCACHE);12  驗證(spylfs)。 
  6. 重命名(當量(usercache),任何(路徑。類),任何()); // <=13  驗 
  7. 證(spylfs)。mkdir(eq(usercache),....);1415  //邏輯塊#216  路 
  8. 徑 publicCache  =  新 路徑(p,ContainerLocalizer。FILECACHE);17  驗 
  9. 證(spylfs)。重命名(當量(usercache),任何(路徑。類),任何 
  10. ()); // <=18歲  驗證(spylfs)。 
  11. mkdir(eq(publicCache),....);19   ....20  }21  ....22} 

最后,再次是V6072 =)。用于查看可疑片段的變量: usercache 和publicCache。

結論

開發中編寫了成千上萬行代碼。生產代碼通常保持清潔,沒有錯誤,缺陷和缺陷(開發人員測試他們的代碼,檢查代碼等)。在這方面,測試肯定不如。測試中的缺陷很容易隱藏在“綠色刻度”后面。正如您可能從今天的警告回顧中了解到的那樣,綠色測試并不總是一項成功的檢查。

這次,當檢查Apache Hadoop代碼庫時,在生產代碼和測試中都非常需要靜態分析,而靜態分析在開發中也起著重要作用。因此,如果您關心代碼和測試質量,建議您著眼于靜態分析。

 

責任編輯:未麗燕 來源: 今日頭條
相關推薦

2012-12-17 10:01:27

Google DremApache Hado云計算

2022-06-01 13:52:11

開源大數據

2020-05-18 07:00:00

性能測試壓力測試負載測試

2011-06-08 16:59:04

性能測試載測試壓力測試

2013-03-21 10:51:06

開發者代碼質量開發經驗

2021-01-05 10:32:12

系統代碼測試

2009-12-18 10:24:28

VS 2010代碼

2023-06-12 16:45:20

數據管理

2023-09-07 15:16:06

軟件開發測試

2024-04-26 11:14:34

C#單元測試框架

2024-05-24 09:57:34

2023-02-15 18:22:11

測試測試左移開發

2012-05-28 09:23:40

JavaHadoopApache

2022-03-25 09:22:42

代碼開發

2020-05-27 11:20:37

HadoopSpark大數據

2023-04-20 08:01:13

2021-08-11 08:00:00

腳本測試開發

2010-12-02 10:30:09

Apache Hado反模式Map Reduce

2011-11-29 09:10:11

Hadoop

2019-10-14 10:09:28

ApacheHiveSpark
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91精品国产综合久久精品 | 国产福利观看 | 国产精品欧美一区二区 | 狠狠操狠狠搞 | 久久精品久久精品久久精品 | 日韩三级 | 成人性生交大免费 | 欧美午夜一区 | 精产国产伦理一二三区 | 亚洲国产精品第一区二区 | а_天堂中文最新版地址 | 久草在线在线精品观看 | 成人免费视频 | 91精品国产91久久久久久吃药 | 性视频一区 | 久草视频2 | 特级黄一级播放 | 久久久精品一区 | 欧美日韩一区二区视频在线观看 | 亚洲一区二区久久 | 性高湖久久久久久久久 | 日韩欧美精品在线 | 天天干天天操天天爽 | 成人精品鲁一区一区二区 | 亚洲国产一区二区三区 | 老妇激情毛片免费 | 97在线观视频免费观看 | 日本超碰| 99久久影院 | 99久久电影| 97av在线| 久久久久久国产精品 | 久久av一区二区三区 | 日韩欧美视频 | 欧美日韩亚洲在线 | 中文字幕在线第一页 | 久久99精品久久久久久 | 久久综合入口 | 久久精品成人 | 国产精品www | 成人国产精品久久 |