2013-02-26 22 views
12

Tôi đang viết một trình bao bọc mỏng quanh Từ điển được thiết kế để an toàn chỉ. Như vậy, một số khóa được yêu cầu và phần lớn logic là đảm bảo mọi thứ được khóa đúng cách và được truy cập theo cách an toàn.Có thể giả/giả mạo xung quanh để tạo ra một chiếc khóa bị thiếu gây ra một thử nghiệm không?

Bây giờ, tôi đang cố gắng kiểm tra đơn vị đó. Một điều lớn tôi muốn thử nghiệm đơn vị là hành vi khóa, để đảm bảo nó là chính xác. Tuy nhiên, tôi chưa bao giờ thấy điều này được thực hiện bất cứ nơi nào vì vậy tôi không chắc chắn làm thế nào để đi về nó. Ngoài ra, tôi biết tôi chỉ có thể sử dụng một loạt các chủ đề để ném công cụ vào tường, nhưng với loại thử nghiệm này, không có đảm bảo nó sẽ thất bại khi nó sai. Đó là hành vi được xác định bởi OS với lập lịch trình chuỗi.

Có những cách nào để đảm bảo rằng hành vi khóa của tôi là chính xác với các bài kiểm tra đơn vị?

+5

+1 về khái niệm của câu hỏi; tò mò tại sao bạn không sử dụng 'ConcurrentDictionary' cho trường hợp cụ thể này. –

+0

@TimMedora thư viện lớp di động nhắm mục tiêu Windows Phone: ( – Earlz

+0

Hiểu được. Từ kinh nghiệm của tôi, việc đánh bom lớp an toàn được đề xuất với hàng nghìn hoạt động (chuỗi chéo, chuỗi đa dạng) sẽ nhanh chóng tiết lộ các vấn đề, nhưng tất nhiên đó không phải là yếu tố quyết định. –

Trả lời

1

Tôi không nghĩ rằng chỉ với Dictionary bản thân bạn có thể đạt được các kiểm tra đáng tin cậy - mục tiêu của bạn là làm cho 2 cuộc gọi chạy song song, điều này sẽ không xảy ra đáng tin cậy.

Bạn có thể thử có từ điển tùy chỉnh (nghĩa là lấy từ từ thông thường) và thêm gọi lại cho tất cả các phương thức Get/Add. Hơn bạn sẽ có thể trì hoãn các cuộc gọi trong 2 chủ đề khi cần thiết ... Bạn sẽ cần đồng bộ hóa riêng biệt giữa 2 chủ đề để làm cho mã thử nghiệm của bạn chạy theo cách bạn muốn và không bế tắc tất cả các thời gian.

+0

Tôi đã kết thúc việc này. Tôi xây dựng trên exaclty làm thế nào tôi đã làm điều này dưới đây – Earlz

3

Khóa chỉ là chi tiết triển khai. Bạn nên giả lập bản thân tình trạng cuộc đua và kiểm tra xem dữ liệu có bị mất tính toàn vẹn của nó trong thử nghiệm hay không.

Điều này sẽ là một lợi ích nếu bạn quyết định thay đổi việc triển khai từ điển và sử dụng các nguyên tắc đồng bộ hóa khác.

Khóa kiểm tra sẽ chứng minh rằng bạn đang gọi một tuyên bố khóa nơi bạn đang mong đợi nó. Trong khi thử nghiệm với một điều kiện chủng tộc giả lập có thể tiết lộ những nơi bạn không mong đợi để đồng bộ hóa.

+0

Về cơ bản, dựa vào việc bẻ khóa từ điển nếu nó được truy cập đồng thời – Earlz

+0

Không cần phải ở trạng thái chính xác, sẽ được chứng minh bằng thử nghiệm của bạn. – Kimi

+2

Vâng, nó dựa vào các chi tiết thực hiện của từ điển sau đó. Tôi thực sự cần phải kiểm tra rằng từ điển không bao giờ cố gắng truy cập một cách đồng thời bởi vì toàn bộ điều cơ bản không an toàn cho các mục đích của tôi – Earlz

2

Tôi về cơ bản đã kết thúc làm những gì @Alexei nói. Để cụ thể hơn, đây là những gì tôi đã làm:

  1. Thực hiện một PausingDictionary mà về cơ bản chỉ có một callback cho mọi phương pháp, nhưng nếu không chỉ cần đi qua để một cuốn từ điển thường xuyên
  2. Tóm tắt mã của tôi (sử dụng DI, vv) để tôi có thể sử dụng PausingDictionary thay vì từ điển thông thường khi thử nghiệm
  3. Đã thêm hai ConcurrentDictionaries vào thử nghiệm đơn vị của tôi. Một được gọi là "Truy cập" và được gọi là "GoAhead". Chìa khóa để thiis là một sự kết hợp của "action"+Thread.GetHashCode().ToString() (trong đó hành động khác nhau đối với mỗi cuộc gọi lại)
  4. Khởi tạo mọi thứ thành sai và thêm một số phương pháp mở rộng để làm việc với nó dễ dàng hơn một chút
  5. Thiết lập các cuộc gọi lại của từ điển để truy cập chuỗi thành đúng, nhưng sau đó nó sẽ đợi trong cuộc gọi lại cho đến khi GoAhead là đúng
  6. Bắt đầu hai chuỗi từ trong thử nghiệm đơn vị. Một chuỗi sẽ truy cập từ điển, nhưng vì GoAhead là sai đối với chuỗi đó, nên nó sẽ nằm ở đó. Chuỗi thứ hai sau đó cũng sẽ cố gắng truy cập từ điển
  7. Tôi muốn xác nhận rằng Accessed cho chuỗi đó là sai, vì mã của tôi nên khóa nó.

Còn hơn thế nữa. Tôi cũng cần chế nhạo một người theo chủ nghĩa IList, nhưng tôi không nghĩ là tôi sẽ làm thế.Những bài kiểm tra đơn vị, trong khi có giá trị, chắc chắn không phải là điều dễ nhất trên thế giới để viết. Ngoài mã cài đặt và triển khai giao diện giả mạo và như vậy, mỗi thử nghiệm kết thúc bằng khoảng 25 dòng mã không phải là bản mẫu. Khóa cứng. Chứng minh rằng khóa của bạn có hiệu quả thậm chí còn khó hơn. Thật ngạc nhiên, kiểu mẫu này có thể cho phép bạn kiểm tra hầu như bất kỳ kịch bản nào. Tuy nhiên, nó rất dài dòng và không thực hiện cho các thử nghiệm đẹp như vậy

Vì vậy, mặc dù thật khó để viết các bài kiểm tra, điều này hoạt động hoàn hảo. Khi tôi tháo khóa luôn thất bại và khi tôi thêm lại khóa, nó luôn xuyên qua.

Edit:

Tôi nghĩ rằng phương pháp này "điều khiển xen kẽ" của chủ đề cũng sẽ làm cho nó có thể để kiểm tra thread-an toàn, cho rằng bạn viết một bài kiểm tra đối với từng xen kẽ càng tốt. Với một số mã này sẽ là không thể, nhưng tôi chỉ muốn nói điều này là không có cách nào giới hạn chỉ mã khóa. Bạn có thể thực hiện cùng một cách sao chép liên tục một lỗi an toàn theo chủ đề như foo.Contains(x) và sau đó var tmp=foo[x]

+0

+1: rất đẹp ghi! –